mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Group boosts
This commit is contained in:
parent
b4b90b090c
commit
b909d1bea0
@ -11092,3 +11092,8 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Notification.Boost.SingleYou" = "You boosted the group";
|
||||
"Notification.Boost.MultipleYou" = "You boosted the group %1$@";
|
||||
|
||||
"Contacts.SelectedContacts_1" = "%@ Selected";
|
||||
"Contacts.SelectedContacts_any" = "%@ Selected";
|
||||
|
||||
"Emoji.GroupEmoji" = "GROUP EMOJI";
|
||||
|
@ -1067,7 +1067,7 @@ public final class Camera {
|
||||
}
|
||||
}
|
||||
}
|
||||
e
|
||||
|
||||
public final class CameraHolder {
|
||||
public let camera: Camera
|
||||
public let previewView: CameraPreviewView
|
||||
|
@ -118,6 +118,7 @@ public class ContactsController: ViewController {
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
private var authorizationDisposable: Disposable?
|
||||
private var selectionDisposable: Disposable?
|
||||
private var actionDisposable = MetaDisposable()
|
||||
private let sortOrderPromise = Promise<ContactsSortOrder>()
|
||||
private let isInVoiceOver = ValuePromise<Bool>(false)
|
||||
@ -234,6 +235,7 @@ public class ContactsController: ViewController {
|
||||
self.presentationDataDisposable?.dispose()
|
||||
self.authorizationDisposable?.dispose()
|
||||
self.actionDisposable.dispose()
|
||||
self.selectionDisposable?.dispose()
|
||||
}
|
||||
|
||||
private func updateThemeAndStrings() {
|
||||
@ -343,8 +345,21 @@ public class ContactsController: ViewController {
|
||||
self?.activateSearch()
|
||||
}
|
||||
|
||||
self.contactsNode.contactListNode.openPeer = { peer, _ in
|
||||
openPeer(peer, false)
|
||||
self.contactsNode.contactListNode.openPeer = { [weak self] peer, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let _ = self.contactsNode.contactListNode.selectionState {
|
||||
self.contactsNode.contactListNode.updateSelectionState({ current in
|
||||
if let updatedState = current?.withToggledPeerId(peer.id), !updatedState.selectedPeerIndices.isEmpty {
|
||||
return updatedState
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
} else {
|
||||
openPeer(peer, false)
|
||||
}
|
||||
}
|
||||
|
||||
self.contactsNode.requestAddContact = { [weak self] phoneNumber in
|
||||
@ -471,9 +486,46 @@ public class ContactsController: ViewController {
|
||||
self?.presentSortMenu(sourceView: sourceNode.view, gesture: gesture)
|
||||
}
|
||||
|
||||
let previousToolbarValue = Atomic<Toolbar?>(value: nil)
|
||||
self.selectionDisposable = (self.contactsNode.contactListNode.selectionStateSignal
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
guard let self, let layout = self.validLayout else {
|
||||
return
|
||||
}
|
||||
|
||||
let toolbar: Toolbar?
|
||||
if let state, state.selectedPeerIndices.count > 0 {
|
||||
toolbar = Toolbar(leftAction: nil, rightAction: nil, middleAction: ToolbarAction(title: self.presentationData.strings.ContactList_DeleteConfirmation(Int32(state.selectedPeerIndices.count)), isEnabled: true, color: .custom(self.presentationData.theme.actionSheet.destructiveActionTextColor)))
|
||||
} else {
|
||||
toolbar = nil
|
||||
}
|
||||
|
||||
let _ = self.contactsNode.updateNavigationBar(layout: layout, transition: .animated(duration: 0.2, curve: .easeInOut))
|
||||
|
||||
var transition: ContainedViewLayoutTransition = .immediate
|
||||
let previousToolbar = previousToolbarValue.swap(toolbar)
|
||||
if (previousToolbar == nil) != (toolbar == nil) {
|
||||
transition = .animated(duration: 0.4, curve: .spring)
|
||||
}
|
||||
self.setToolbar(toolbar, transition: transition)
|
||||
})
|
||||
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
override public func toolbarActionSelected(action: ToolbarActionOption) {
|
||||
guard case .middle = action, let selectionState = self.contactsNode.contactListNode.selectionState else {
|
||||
return
|
||||
}
|
||||
var peerIds: [EnginePeer.Id] = []
|
||||
for contactPeerId in selectionState.selectedPeerIndices.keys {
|
||||
if case let .peer(peerId) = contactPeerId {
|
||||
peerIds.append(peerId)
|
||||
}
|
||||
}
|
||||
self.requestDeleteContacts(peerIds: peerIds)
|
||||
}
|
||||
|
||||
override public func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
@ -587,6 +639,9 @@ public class ContactsController: ViewController {
|
||||
}
|
||||
|
||||
public func requestDeleteContacts(peerIds: [EnginePeer.Id]) {
|
||||
guard !peerIds.isEmpty else {
|
||||
return
|
||||
}
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
@ -604,6 +659,10 @@ public class ContactsController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
self.contactsNode.contactListNode.updateSelectionState { _ in
|
||||
return nil
|
||||
}
|
||||
|
||||
self.contactsNode.contactListNode.updatePendingRemovalPeerIds { state in
|
||||
var state = state
|
||||
for peerId in peerIds {
|
||||
|
@ -297,16 +297,31 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
return false
|
||||
}
|
||||
|
||||
private func updateNavigationBar(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) -> (navigationHeight: CGFloat, storiesInset: CGFloat) {
|
||||
func updateNavigationBar(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) -> (navigationHeight: CGFloat, storiesInset: CGFloat) {
|
||||
let tabsNode: ASDisplayNode? = nil
|
||||
let tabsNodeIsSearch = false
|
||||
|
||||
let primaryContent = ChatListHeaderComponent.Content(
|
||||
title: self.presentationData.strings.Contacts_Title,
|
||||
navigationBackTitle: nil,
|
||||
titleComponent: nil,
|
||||
chatListTitle: NetworkStatusTitle(text: self.presentationData.strings.Contacts_Title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false, peerStatus: nil),
|
||||
leftButton: AnyComponentWithIdentity(id: "sort", component: AnyComponent(NavigationButtonComponent(
|
||||
let title: String
|
||||
let leftButton: AnyComponentWithIdentity<NavigationButtonComponentEnvironment>?
|
||||
let rightButtons: [AnyComponentWithIdentity<NavigationButtonComponentEnvironment>]
|
||||
|
||||
if let selectionState = self.contactListNode.selectionState {
|
||||
title = self.presentationData.strings.Contacts_SelectedContacts(Int32(selectionState.selectedPeerIndices.count))
|
||||
leftButton = AnyComponentWithIdentity(id: "done", component: AnyComponent(NavigationButtonComponent(
|
||||
content: .text(title: self.presentationData.strings.Common_Done, isBold: true),
|
||||
pressed: { [weak self] sourceView in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.contactListNode.updateSelectionState { _ in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
)))
|
||||
rightButtons = []
|
||||
} else {
|
||||
title = self.presentationData.strings.Contacts_Title
|
||||
leftButton = AnyComponentWithIdentity(id: "sort", component: AnyComponent(NavigationButtonComponent(
|
||||
content: .text(title: self.presentationData.strings.Contacts_Sort, isBold: false),
|
||||
pressed: { [weak self] sourceView in
|
||||
guard let self else {
|
||||
@ -315,8 +330,8 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
|
||||
self.controller?.presentSortMenu(sourceView: sourceView, gesture: nil)
|
||||
}
|
||||
))),
|
||||
rightButtons: [AnyComponentWithIdentity(id: "add", component: AnyComponent(NavigationButtonComponent(
|
||||
)))
|
||||
rightButtons = [AnyComponentWithIdentity(id: "add", component: AnyComponent(NavigationButtonComponent(
|
||||
content: .icon(imageName: "Chat List/AddIcon"),
|
||||
pressed: { [weak self] _ in
|
||||
guard let self else {
|
||||
@ -324,7 +339,16 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
}
|
||||
self.controller?.addPressed()
|
||||
}
|
||||
)))],
|
||||
)))]
|
||||
}
|
||||
|
||||
let primaryContent = ChatListHeaderComponent.Content(
|
||||
title: self.presentationData.strings.Contacts_Title,
|
||||
navigationBackTitle: nil,
|
||||
titleComponent: nil,
|
||||
chatListTitle: NetworkStatusTitle(text: title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false, peerStatus: nil),
|
||||
leftButton: leftButton,
|
||||
rightButtons: rightButtons,
|
||||
backTitle: nil,
|
||||
backPressed: nil
|
||||
)
|
||||
|
@ -672,6 +672,7 @@ final class PenTool: DrawingElement {
|
||||
return self.start.location.distance(to: self.end.location)
|
||||
}
|
||||
}
|
||||
|
||||
private func smoothPoints(_ input: SmootherInput) -> [Point] {
|
||||
let segmentDistance: CGFloat = 6.0
|
||||
let distance = input.distance
|
||||
|
@ -963,7 +963,7 @@ public final class ManagedAudioSession: NSObject {
|
||||
if case let .record(_, video, _) = type, video, let input = AVAudioSession.sharedInstance().availableInputs?.first {
|
||||
if let dataSources = input.dataSources {
|
||||
for source in dataSources {
|
||||
if source.dataSourceName.contains("Front") {
|
||||
if source.dataSourceName.contains("Bottom") {
|
||||
try? input.setPreferredDataSource(source)
|
||||
break
|
||||
}
|
||||
|
@ -129,7 +129,26 @@ func _internal_applyChannelBoost(account: Account, peerId: PeerId, slots: [Int32
|
||||
|> mapToSignal { result -> Signal<MyBoostStatus?, NoError> in
|
||||
if let result = result {
|
||||
return account.postbox.transaction { transaction -> MyBoostStatus? in
|
||||
return MyBoostStatus(apiMyBoostStatus: result, accountPeerId: account.peerId, transaction: transaction)
|
||||
let myBoostStatus = MyBoostStatus(apiMyBoostStatus: result, accountPeerId: account.peerId, transaction: transaction)
|
||||
|
||||
var appliedBoosts: Int32 = 0
|
||||
for boost in myBoostStatus.boosts {
|
||||
if boost.peer?.id == peerId {
|
||||
appliedBoosts += 1
|
||||
}
|
||||
}
|
||||
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
var cachedData: CachedChannelData
|
||||
if let current = current as? CachedChannelData {
|
||||
cachedData = current
|
||||
} else {
|
||||
cachedData = CachedChannelData()
|
||||
}
|
||||
return cachedData.withUpdatedAppliedBoosts(appliedBoosts)
|
||||
})
|
||||
|
||||
return myBoostStatus
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
|
@ -533,7 +533,7 @@ public final class CachedChannelData: CachedPeerData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: boostsToUnrestrict, appliedBoosts: self.appliedBoosts, emojiPack: self.emojiPack)
|
||||
}
|
||||
|
||||
public func withUpdateAppliedBoosts(_ appliedBoosts: Int32?) -> CachedChannelData {
|
||||
public func withUpdatedAppliedBoosts(_ appliedBoosts: Int32?) -> CachedChannelData {
|
||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, invitedOn: self.invitedOn, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon, inviteRequestsPending: self.inviteRequestsPending, sendAsPeerId: self.sendAsPeerId, allowedReactions: self.allowedReactions, membersHidden: self.membersHidden, viewForumAsMessages: self.viewForumAsMessages, wallpaper: self.wallpaper, boostsToUnrestrict: self.boostsToUnrestrict, appliedBoosts: appliedBoosts, emojiPack: self.emojiPack)
|
||||
}
|
||||
|
||||
|
@ -675,7 +675,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
.withUpdatedViewForumAsMessages(.known(forumViewAsMessages))
|
||||
.withUpdatedWallpaper(wallpaper)
|
||||
.withUpdatedBoostsToUnrestrict(boostsUnrestrict)
|
||||
.withUpdateAppliedBoosts(appliedBoosts)
|
||||
.withUpdatedAppliedBoosts(appliedBoosts)
|
||||
.withUpdatedEmojiPack(emojiPack)
|
||||
})
|
||||
|
||||
|
@ -278,7 +278,7 @@ public struct PresentationResourcesItemList {
|
||||
|
||||
public static func addBoostsIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.itemListAddBoostsIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Premium/AddBoosts"), color: theme.list.itemAccentColor)
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Premium/Gift"), color: theme.list.itemAccentColor)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1257,8 +1257,7 @@ public extension EmojiPagerContentComponent {
|
||||
itemGroups[groupIndex].items.append(resultItem)
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
//TODO:localize
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.info.title, subtitle: nil, badge: "GROUP EMOJI", isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.info.title, subtitle: nil, badge: strings.Emoji_GroupEmoji, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,7 +571,7 @@ public final class EntityKeyboardComponent: Component {
|
||||
var topEmojiItems: [EntityKeyboardTopPanelComponent.Item] = []
|
||||
for itemGroup in emojiContent.panelItemGroups {
|
||||
if !itemGroup.items.isEmpty {
|
||||
if let id = itemGroup.groupId.base as? String {
|
||||
if let id = itemGroup.groupId.base as? String, id != "peerSpecific" {
|
||||
if id == "recent" || id == "liked" {
|
||||
let iconMapping: [String: EntityKeyboardIconTopPanelComponent.Icon] = [
|
||||
"recent": .recent,
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Premium/Gift.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/Gift.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "gift_30.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
443
submodules/TelegramUI/Images.xcassets/Premium/Gift.imageset/gift_30.pdf
vendored
Normal file
443
submodules/TelegramUI/Images.xcassets/Premium/Gift.imageset/gift_30.pdf
vendored
Normal file
@ -0,0 +1,443 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 6.250000 3.669434 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.665000 11.330566 m
|
||||
0.665000 11.697836 0.367269 11.995566 0.000000 11.995566 c
|
||||
-0.367269 11.995566 -0.665000 11.697836 -0.665000 11.330566 c
|
||||
0.665000 11.330566 l
|
||||
h
|
||||
18.165001 11.330566 m
|
||||
18.165001 11.697836 17.867270 11.995566 17.500000 11.995566 c
|
||||
17.132730 11.995566 16.834999 11.697836 16.834999 11.330566 c
|
||||
18.165001 11.330566 l
|
||||
h
|
||||
1.365024 1.603050 m
|
||||
1.666927 2.195569 l
|
||||
1.365024 1.603050 l
|
||||
h
|
||||
0.272484 2.695590 m
|
||||
0.865003 2.997494 l
|
||||
0.272484 2.695590 l
|
||||
h
|
||||
16.134975 1.603050 m
|
||||
16.436880 1.010530 l
|
||||
16.134975 1.603050 l
|
||||
h
|
||||
17.227516 2.695590 m
|
||||
17.820036 2.393686 l
|
||||
17.227516 2.695590 l
|
||||
h
|
||||
13.500000 1.995566 m
|
||||
4.000000 1.995566 l
|
||||
4.000000 0.665566 l
|
||||
13.500000 0.665566 l
|
||||
13.500000 1.995566 l
|
||||
h
|
||||
0.665000 5.330566 m
|
||||
0.665000 11.330566 l
|
||||
-0.665000 11.330566 l
|
||||
-0.665000 5.330566 l
|
||||
0.665000 5.330566 l
|
||||
h
|
||||
16.834999 11.330566 m
|
||||
16.834999 5.330566 l
|
||||
18.165001 5.330566 l
|
||||
18.165001 11.330566 l
|
||||
16.834999 11.330566 l
|
||||
h
|
||||
4.000000 1.995566 m
|
||||
3.288961 1.995566 2.795676 1.996083 2.412157 2.027418 c
|
||||
2.036401 2.058119 1.824946 2.115055 1.666927 2.195569 c
|
||||
1.063120 1.010530 l
|
||||
1.439881 0.818562 1.845848 0.739256 2.303853 0.701836 c
|
||||
2.754094 0.665050 3.310907 0.665566 4.000000 0.665566 c
|
||||
4.000000 1.995566 l
|
||||
h
|
||||
-0.665000 5.330566 m
|
||||
-0.665000 4.641474 -0.665517 4.084661 -0.628731 3.634419 c
|
||||
-0.591311 3.176414 -0.512005 2.770447 -0.320036 2.393686 c
|
||||
0.865003 2.997494 l
|
||||
0.784489 3.155513 0.727552 3.366968 0.696852 3.742723 c
|
||||
0.665517 4.126243 0.665000 4.619528 0.665000 5.330566 c
|
||||
-0.665000 5.330566 l
|
||||
h
|
||||
1.666927 2.195569 m
|
||||
1.321650 2.371497 1.040931 2.652216 0.865003 2.997494 c
|
||||
-0.320036 2.393686 l
|
||||
-0.016596 1.798154 0.467587 1.313970 1.063120 1.010530 c
|
||||
1.666927 2.195569 l
|
||||
h
|
||||
13.500000 0.665566 m
|
||||
14.189093 0.665566 14.745906 0.665050 15.196147 0.701836 c
|
||||
15.654152 0.739256 16.060120 0.818562 16.436880 1.010530 c
|
||||
15.833073 2.195569 l
|
||||
15.675054 2.115055 15.463599 2.058119 15.087843 2.027418 c
|
||||
14.704324 1.996083 14.211039 1.995566 13.500000 1.995566 c
|
||||
13.500000 0.665566 l
|
||||
h
|
||||
16.834999 5.330566 m
|
||||
16.834999 4.619527 16.834482 4.126243 16.803148 3.742723 c
|
||||
16.772448 3.366968 16.715511 3.155513 16.634996 2.997494 c
|
||||
17.820036 2.393686 l
|
||||
18.012005 2.770447 18.091311 3.176414 18.128731 3.634419 c
|
||||
18.165518 4.084660 18.165001 4.641474 18.165001 5.330566 c
|
||||
16.834999 5.330566 l
|
||||
h
|
||||
16.436880 1.010530 m
|
||||
17.032413 1.313970 17.516596 1.798154 17.820036 2.393686 c
|
||||
16.634996 2.997494 l
|
||||
16.459070 2.652216 16.178350 2.371497 15.833073 2.195569 c
|
||||
16.436880 1.010530 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 5.000000 14.293945 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
2.500000 0.666055 m
|
||||
2.867269 0.666055 3.165000 0.963785 3.165000 1.331055 c
|
||||
3.165000 1.698324 2.867269 1.996055 2.500000 1.996055 c
|
||||
2.500000 0.666055 l
|
||||
h
|
||||
17.500000 1.996055 m
|
||||
17.132730 1.996055 16.834999 1.698324 16.834999 1.331055 c
|
||||
16.834999 0.963785 17.132730 0.666055 17.500000 0.666055 c
|
||||
17.500000 1.996055 l
|
||||
h
|
||||
0.144016 2.189722 m
|
||||
-0.457137 1.905398 l
|
||||
0.144016 2.189722 l
|
||||
h
|
||||
0.858667 1.475071 m
|
||||
1.142991 2.076224 l
|
||||
0.858667 1.475071 l
|
||||
h
|
||||
19.855984 2.189722 m
|
||||
20.457136 1.905398 l
|
||||
19.855984 2.189722 l
|
||||
h
|
||||
19.141333 1.475071 m
|
||||
18.857008 2.076224 l
|
||||
19.141333 1.475071 l
|
||||
h
|
||||
18.568888 7.341028 m
|
||||
18.284563 6.739875 l
|
||||
18.568888 7.341028 l
|
||||
h
|
||||
19.759974 6.149942 m
|
||||
19.158821 5.865618 l
|
||||
19.759974 6.149942 l
|
||||
h
|
||||
3.906250 6.916055 m
|
||||
16.093750 6.916055 l
|
||||
16.093750 8.246055 l
|
||||
3.906250 8.246055 l
|
||||
3.906250 6.916055 l
|
||||
h
|
||||
2.343750 0.666055 m
|
||||
2.500000 0.666055 l
|
||||
2.500000 1.996055 l
|
||||
2.343750 1.996055 l
|
||||
2.343750 0.666055 l
|
||||
h
|
||||
17.656250 1.996055 m
|
||||
17.500000 1.996055 l
|
||||
17.500000 0.666055 l
|
||||
17.656250 0.666055 l
|
||||
17.656250 1.996055 l
|
||||
h
|
||||
-0.665000 3.674805 m
|
||||
-0.665000 3.291543 -0.665455 2.966613 -0.645052 2.700472 c
|
||||
-0.624109 2.427277 -0.578354 2.161689 -0.457137 1.905398 c
|
||||
0.745169 2.474046 l
|
||||
0.722370 2.522251 0.696117 2.605676 0.681057 2.802133 c
|
||||
0.665455 3.005646 0.665000 3.271009 0.665000 3.674805 c
|
||||
-0.665000 3.674805 l
|
||||
h
|
||||
2.343750 1.996055 m
|
||||
1.939954 1.996055 1.674591 1.996510 1.471079 2.012111 c
|
||||
1.274621 2.027172 1.191196 2.053424 1.142991 2.076224 c
|
||||
0.574343 0.873918 l
|
||||
0.830635 0.752701 1.096222 0.706945 1.369418 0.686002 c
|
||||
1.635558 0.665600 1.960488 0.666055 2.343750 0.666055 c
|
||||
2.343750 1.996055 l
|
||||
h
|
||||
-0.457137 1.905398 m
|
||||
-0.242981 1.452604 0.121549 1.088073 0.574343 0.873918 c
|
||||
1.142991 2.076224 l
|
||||
0.968357 2.158820 0.827765 2.299412 0.745169 2.474046 c
|
||||
-0.457137 1.905398 l
|
||||
h
|
||||
19.334999 3.674805 m
|
||||
19.334999 3.271009 19.334545 3.005646 19.318943 2.802133 c
|
||||
19.303883 2.605676 19.277630 2.522251 19.254831 2.474046 c
|
||||
20.457136 1.905398 l
|
||||
20.578354 2.161689 20.624109 2.427277 20.645052 2.700472 c
|
||||
20.665455 2.966613 20.665001 3.291543 20.665001 3.674805 c
|
||||
19.334999 3.674805 l
|
||||
h
|
||||
17.656250 0.666055 m
|
||||
18.039513 0.666055 18.364443 0.665600 18.630583 0.686002 c
|
||||
18.903778 0.706945 19.169365 0.752701 19.425657 0.873918 c
|
||||
18.857008 2.076224 l
|
||||
18.808804 2.053424 18.725378 2.027172 18.528921 2.012111 c
|
||||
18.325409 1.996510 18.060045 1.996055 17.656250 1.996055 c
|
||||
17.656250 0.666055 l
|
||||
h
|
||||
19.254831 2.474046 m
|
||||
19.172235 2.299412 19.031643 2.158820 18.857008 2.076224 c
|
||||
19.425657 0.873918 l
|
||||
19.878450 1.088073 20.242981 1.452604 20.457136 1.905398 c
|
||||
19.254831 2.474046 l
|
||||
h
|
||||
16.093750 6.916055 m
|
||||
16.759899 6.916055 17.222025 6.915600 17.582088 6.887997 c
|
||||
17.935097 6.860935 18.134859 6.810679 18.284563 6.739875 c
|
||||
18.853212 7.942181 l
|
||||
18.495422 8.111403 18.113497 8.181161 17.683750 8.214106 c
|
||||
17.261059 8.246510 16.739365 8.246055 16.093750 8.246055 c
|
||||
16.093750 6.916055 l
|
||||
h
|
||||
20.665001 3.674805 m
|
||||
20.665001 4.320419 20.665455 4.842113 20.633051 5.264805 c
|
||||
20.600107 5.694551 20.530348 6.076477 20.361126 6.434267 c
|
||||
19.158821 5.865618 l
|
||||
19.229626 5.715915 19.279881 5.516152 19.306942 5.163144 c
|
||||
19.334545 4.803081 19.334999 4.340953 19.334999 3.674805 c
|
||||
20.665001 3.674805 l
|
||||
h
|
||||
18.284563 6.739875 m
|
||||
18.668341 6.558362 18.977308 6.249395 19.158821 5.865618 c
|
||||
20.361126 6.434267 l
|
||||
20.048054 7.096203 19.515148 7.629108 18.853212 7.942181 c
|
||||
18.284563 6.739875 l
|
||||
h
|
||||
3.906250 8.246055 m
|
||||
3.260636 8.246055 2.738941 8.246510 2.316250 8.214106 c
|
||||
1.886503 8.181161 1.504578 8.111403 1.146788 7.942181 c
|
||||
1.715436 6.739875 l
|
||||
1.865140 6.810679 2.064903 6.860935 2.417911 6.887997 c
|
||||
2.777974 6.915600 3.240102 6.916055 3.906250 6.916055 c
|
||||
3.906250 8.246055 l
|
||||
h
|
||||
0.665000 3.674805 m
|
||||
0.665000 4.340953 0.665455 4.803081 0.693058 5.163144 c
|
||||
0.720120 5.516152 0.770375 5.715915 0.841180 5.865618 c
|
||||
-0.361126 6.434267 l
|
||||
-0.530348 6.076477 -0.600106 5.694551 -0.633051 5.264805 c
|
||||
-0.665455 4.842113 -0.665000 4.320419 -0.665000 3.674805 c
|
||||
0.665000 3.674805 l
|
||||
h
|
||||
1.146788 7.942181 m
|
||||
0.484851 7.629108 -0.048053 7.096203 -0.361126 6.434267 c
|
||||
0.841180 5.865618 l
|
||||
1.022693 6.249395 1.331660 6.558362 1.715436 6.739875 c
|
||||
1.146788 7.942181 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 10.000000 20.544922 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
5.000000 1.330078 m
|
||||
5.000000 0.665078 l
|
||||
5.665000 0.665078 l
|
||||
5.665000 1.330078 l
|
||||
5.000000 1.330078 l
|
||||
h
|
||||
4.335000 3.830078 m
|
||||
4.335000 1.330078 l
|
||||
5.665000 1.330078 l
|
||||
5.665000 3.830078 l
|
||||
4.335000 3.830078 l
|
||||
h
|
||||
5.000000 1.995078 m
|
||||
2.500000 1.995078 l
|
||||
2.500000 0.665078 l
|
||||
5.000000 0.665078 l
|
||||
5.000000 1.995078 l
|
||||
h
|
||||
2.500000 1.995078 m
|
||||
1.486557 1.995078 0.665000 2.816636 0.665000 3.830078 c
|
||||
-0.665000 3.830078 l
|
||||
-0.665000 2.082097 0.752019 0.665078 2.500000 0.665078 c
|
||||
2.500000 1.995078 l
|
||||
h
|
||||
2.500000 5.665078 m
|
||||
3.513443 5.665078 4.335000 4.843521 4.335000 3.830078 c
|
||||
5.665000 3.830078 l
|
||||
5.665000 5.578059 4.247981 6.995078 2.500000 6.995078 c
|
||||
2.500000 5.665078 l
|
||||
h
|
||||
2.500000 6.995078 m
|
||||
0.752019 6.995078 -0.665000 5.578059 -0.665000 3.830078 c
|
||||
0.665000 3.830078 l
|
||||
0.665000 4.843521 1.486557 5.665078 2.500000 5.665078 c
|
||||
2.500000 6.995078 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 15.000000 20.544922 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 1.330078 m
|
||||
-0.665000 1.330078 l
|
||||
-0.665000 0.665078 l
|
||||
0.000000 0.665078 l
|
||||
0.000000 1.330078 l
|
||||
h
|
||||
2.500000 1.995078 m
|
||||
0.000000 1.995078 l
|
||||
0.000000 0.665078 l
|
||||
2.500000 0.665078 l
|
||||
2.500000 1.995078 l
|
||||
h
|
||||
0.665000 1.330078 m
|
||||
0.665000 3.830078 l
|
||||
-0.665000 3.830078 l
|
||||
-0.665000 1.330078 l
|
||||
0.665000 1.330078 l
|
||||
h
|
||||
4.335000 3.830078 m
|
||||
4.335000 2.816636 3.513443 1.995078 2.500000 1.995078 c
|
||||
2.500000 0.665078 l
|
||||
4.247981 0.665078 5.665000 2.082097 5.665000 3.830078 c
|
||||
4.335000 3.830078 l
|
||||
h
|
||||
2.500000 5.665078 m
|
||||
3.513443 5.665078 4.335000 4.843521 4.335000 3.830078 c
|
||||
5.665000 3.830078 l
|
||||
5.665000 5.578059 4.247981 6.995078 2.500000 6.995078 c
|
||||
2.500000 5.665078 l
|
||||
h
|
||||
2.500000 6.995078 m
|
||||
0.752019 6.995078 -0.665000 5.578059 -0.665000 3.830078 c
|
||||
0.665000 3.830078 l
|
||||
0.665000 4.843521 1.486557 5.665078 2.500000 5.665078 c
|
||||
2.500000 6.995078 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 15.000000 4.294922 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.665000 3.830078 m
|
||||
0.665000 4.197348 0.367269 4.495078 0.000000 4.495078 c
|
||||
-0.367269 4.495078 -0.665000 4.197348 -0.665000 3.830078 c
|
||||
0.665000 3.830078 l
|
||||
h
|
||||
-0.665000 1.330078 m
|
||||
-0.665000 0.962809 -0.367269 0.665078 0.000000 0.665078 c
|
||||
0.367269 0.665078 0.665000 0.962809 0.665000 1.330078 c
|
||||
-0.665000 1.330078 l
|
||||
h
|
||||
-0.665000 3.830078 m
|
||||
-0.665000 1.330078 l
|
||||
0.665000 1.330078 l
|
||||
0.665000 3.830078 l
|
||||
-0.665000 3.830078 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 9.990234 9.851074 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
4.751247 1.595008 m
|
||||
2.492245 0.211133 l
|
||||
2.257351 0.067236 1.950281 0.141003 1.806384 0.375896 c
|
||||
1.736104 0.490619 1.715151 0.628868 1.748279 0.759263 c
|
||||
2.097972 2.135665 l
|
||||
2.224205 2.632523 2.564205 3.047855 3.026343 3.269736 c
|
||||
5.490801 4.452966 l
|
||||
5.605695 4.508129 5.654118 4.645987 5.598955 4.760881 c
|
||||
5.554282 4.853927 5.453256 4.905994 5.351554 4.888387 c
|
||||
2.608295 4.413459 l
|
||||
2.050655 4.316917 1.478800 4.470905 1.045039 4.834409 c
|
||||
0.178421 5.560659 l
|
||||
-0.032710 5.737593 -0.060432 6.052180 0.116501 6.263311 c
|
||||
0.202556 6.365997 0.326303 6.429747 0.459872 6.440200 c
|
||||
3.107648 6.647414 l
|
||||
3.294706 6.662054 3.457723 6.780433 3.529533 6.953778 c
|
||||
4.550995 9.419525 l
|
||||
4.656422 9.674018 4.948194 9.794860 5.202687 9.689434 c
|
||||
5.324886 9.638812 5.421974 9.541724 5.472596 9.419525 c
|
||||
6.494058 6.953778 l
|
||||
6.565868 6.780433 6.728885 6.662054 6.915944 6.647414 c
|
||||
9.578268 6.439061 l
|
||||
9.852894 6.417569 10.058100 6.177518 10.036608 5.902892 c
|
||||
10.026269 5.770781 9.963782 5.648214 9.862940 5.562243 c
|
||||
7.832497 3.831244 l
|
||||
7.689560 3.709387 7.627202 3.517563 7.671160 3.334950 c
|
||||
8.295380 0.741805 l
|
||||
8.359848 0.473989 8.195003 0.204619 7.927186 0.140151 c
|
||||
7.798499 0.109174 7.662776 0.130618 7.549908 0.199762 c
|
||||
5.272344 1.595008 l
|
||||
5.112454 1.692957 4.911138 1.692957 4.751247 1.595008 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
10525
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000010615 00000 n
|
||||
0000010639 00000 n
|
||||
0000010812 00000 n
|
||||
0000010886 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
10945
|
||||
%%EOF
|
@ -164,38 +164,38 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
||||
self.backdropNode.update(rect: rect, within: containerSize)
|
||||
}
|
||||
|
||||
var isScheduledMessages = false
|
||||
if case .scheduledMessages = interfaceState.subject {
|
||||
isScheduledMessages = true
|
||||
}
|
||||
|
||||
if let slowmodeState = interfaceState.slowmodeState, !isScheduledMessages && interfaceState.editMessageState == nil {
|
||||
let sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode
|
||||
if let current = self.sendButtonRadialStatusNode {
|
||||
sendButtonRadialStatusNode = current
|
||||
} else {
|
||||
sendButtonRadialStatusNode = ChatSendButtonRadialStatusNode(color: interfaceState.theme.chat.inputPanel.panelControlAccentColor)
|
||||
sendButtonRadialStatusNode.alpha = self.sendContainerNode.alpha
|
||||
self.sendButtonRadialStatusNode = sendButtonRadialStatusNode
|
||||
self.addSubnode(sendButtonRadialStatusNode)
|
||||
}
|
||||
|
||||
transition.updateSublayerTransformScale(layer: self.sendContainerNode.layer, scale: CGPoint(x: 0.7575, y: 0.7575))
|
||||
|
||||
let defaultSendButtonSize: CGFloat = 25.0
|
||||
let defaultOriginX = floorToScreenPixels((self.sendButton.bounds.width - defaultSendButtonSize) / 2.0)
|
||||
let defaultOriginY = floorToScreenPixels((self.sendButton.bounds.height - defaultSendButtonSize) / 2.0)
|
||||
|
||||
let radialStatusFrame = CGRect(origin: CGPoint(x: defaultOriginX - 4.0, y: defaultOriginY - 4.0), size: CGSize(width: 33.0, height: 33.0))
|
||||
sendButtonRadialStatusNode.frame = radialStatusFrame
|
||||
sendButtonRadialStatusNode.slowmodeState = slowmodeState
|
||||
} else {
|
||||
if let sendButtonRadialStatusNode = self.sendButtonRadialStatusNode {
|
||||
self.sendButtonRadialStatusNode = nil
|
||||
sendButtonRadialStatusNode.removeFromSupernode()
|
||||
}
|
||||
transition.updateSublayerTransformScale(layer: self.sendContainerNode.layer, scale: CGPoint(x: 1.0, y: 1.0))
|
||||
}
|
||||
// var isScheduledMessages = false
|
||||
// if case .scheduledMessages = interfaceState.subject {
|
||||
// isScheduledMessages = true
|
||||
// }
|
||||
//
|
||||
// if let slowmodeState = interfaceState.slowmodeState, !isScheduledMessages && interfaceState.editMessageState == nil {
|
||||
// let sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode
|
||||
// if let current = self.sendButtonRadialStatusNode {
|
||||
// sendButtonRadialStatusNode = current
|
||||
// } else {
|
||||
// sendButtonRadialStatusNode = ChatSendButtonRadialStatusNode(color: interfaceState.theme.chat.inputPanel.panelControlAccentColor)
|
||||
// sendButtonRadialStatusNode.alpha = self.sendContainerNode.alpha
|
||||
// self.sendButtonRadialStatusNode = sendButtonRadialStatusNode
|
||||
// self.addSubnode(sendButtonRadialStatusNode)
|
||||
// }
|
||||
//
|
||||
// transition.updateSublayerTransformScale(layer: self.sendContainerNode.layer, scale: CGPoint(x: 0.7575, y: 0.7575))
|
||||
//
|
||||
// let defaultSendButtonSize: CGFloat = 25.0
|
||||
// let defaultOriginX = floorToScreenPixels((self.sendButton.bounds.width - defaultSendButtonSize) / 2.0)
|
||||
// let defaultOriginY = floorToScreenPixels((self.sendButton.bounds.height - defaultSendButtonSize) / 2.0)
|
||||
//
|
||||
// let radialStatusFrame = CGRect(origin: CGPoint(x: defaultOriginX - 4.0, y: defaultOriginY - 4.0), size: CGSize(width: 33.0, height: 33.0))
|
||||
// sendButtonRadialStatusNode.frame = radialStatusFrame
|
||||
// sendButtonRadialStatusNode.slowmodeState = slowmodeState
|
||||
// } else {
|
||||
// if let sendButtonRadialStatusNode = self.sendButtonRadialStatusNode {
|
||||
// self.sendButtonRadialStatusNode = nil
|
||||
// sendButtonRadialStatusNode.removeFromSupernode()
|
||||
// }
|
||||
// transition.updateSublayerTransformScale(layer: self.sendContainerNode.layer, scale: CGPoint(x: 1.0, y: 1.0))
|
||||
// }
|
||||
|
||||
transition.updateFrame(node: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size))
|
||||
let expanded = isMediaInputExpanded
|
||||
|
@ -41,6 +41,8 @@ import ChatContextQuery
|
||||
import ChatInputTextNode
|
||||
import ChatInputPanelNode
|
||||
import TelegramNotices
|
||||
import AnimatedCountLabelNode
|
||||
import TelegramStringFormatting
|
||||
|
||||
private let accessoryButtonFont = Font.medium(14.0)
|
||||
private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.monospacedNumbers])
|
||||
@ -535,6 +537,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
let textInputBackgroundNode: ASImageNode
|
||||
private var transparentTextInputBackgroundImage: UIImage?
|
||||
let actionButtons: ChatTextInputActionButtonsNode
|
||||
private let slowModeButton: BoostSlowModeButton
|
||||
var mediaRecordingAccessibilityArea: AccessibilityAreaNode?
|
||||
private let counterTextNode: ImmediateTextNode
|
||||
|
||||
@ -570,6 +573,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
|
||||
private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool, Bool)?
|
||||
private var leftMenuInset: CGFloat = 0.0
|
||||
private var rightSlowModeInset: CGFloat = 0.0
|
||||
|
||||
var displayAttachmentMenu: () -> Void = { }
|
||||
var sendMessage: () -> Void = { }
|
||||
@ -855,10 +859,18 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
self.counterTextNode = ImmediateTextNode()
|
||||
self.counterTextNode.textAlignment = .center
|
||||
|
||||
self.slowModeButton = BoostSlowModeButton()
|
||||
self.slowModeButton.alpha = 0.0
|
||||
|
||||
self.viewOnceButton = ChatRecordingViewOnceButtonNode(icon: .viewOnce)
|
||||
|
||||
super.init()
|
||||
|
||||
self.slowModeButton.requestUpdate = { [weak self] in
|
||||
self?.requestLayout(transition: .animated(duration: 0.2, curve: .easeInOut))
|
||||
}
|
||||
self.slowModeButton.addTarget(self, action: #selector(self.slowModeButtonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.viewForOverlayContent = ChatTextViewForOverlayContent(
|
||||
ignoreHit: { [weak self] view, point in
|
||||
guard let strongSelf = self else {
|
||||
@ -1045,6 +1057,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
self.clippingNode.addSubnode(self.actionButtons)
|
||||
self.clippingNode.addSubnode(self.counterTextNode)
|
||||
|
||||
self.clippingNode.addSubnode(self.slowModeButton)
|
||||
|
||||
self.clippingNode.view.addSubview(self.searchLayoutClearButton)
|
||||
|
||||
self.textInputBackgroundNode.clipsToBounds = true
|
||||
@ -1416,11 +1430,11 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
}
|
||||
}
|
||||
|
||||
func requestLayout() {
|
||||
func requestLayout(transition: ContainedViewLayoutTransition = .immediate) {
|
||||
guard let presentationInterfaceState = self.presentationInterfaceState, let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded)
|
||||
let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: transition, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded)
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat {
|
||||
@ -1933,11 +1947,21 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
}
|
||||
self.leftMenuInset = leftMenuInset
|
||||
|
||||
var rightSlowModeInset: CGFloat = 0.0
|
||||
var slowModeButtonSize: CGSize = .zero
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
slowModeButtonSize = self.slowModeButton.update(size: CGSize(width: width, height: 44.0), interfaceState: presentationInterfaceState)
|
||||
if inputHasText {
|
||||
rightSlowModeInset = slowModeButtonSize.width - 33.0
|
||||
}
|
||||
}
|
||||
self.rightSlowModeInset = rightSlowModeInset
|
||||
|
||||
if buttonTitleUpdated && !transition.isAnimated {
|
||||
transition = .animated(duration: 0.3, curve: .easeInOut)
|
||||
}
|
||||
|
||||
let baseWidth = width - leftInset - leftMenuInset - rightInset
|
||||
let baseWidth = width - leftInset - leftMenuInset - rightInset - rightSlowModeInset
|
||||
let (accessoryButtonsWidth, textFieldHeight) = self.calculateTextFieldMetrics(width: baseWidth, maxHeight: maxHeight, metrics: metrics)
|
||||
var panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
|
||||
if displayBotStartButton {
|
||||
@ -2332,6 +2356,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, transition: transition, interfaceState: presentationInterfaceState)
|
||||
}
|
||||
|
||||
let slowModeButtonFrame = CGRect(origin: CGPoint(x: hideOffset.x + width - rightInset - 5.0 - slowModeButtonSize.width + composeButtonsOffset, y: hideOffset.y + panelHeight - minimalHeight + 6.0), size: slowModeButtonSize)
|
||||
transition.updateFrame(node: self.slowModeButton, frame: slowModeButtonFrame)
|
||||
|
||||
if let _ = interfaceState.inputTextPanelState.mediaRecordingState {
|
||||
let text: String = interfaceState.strings.VoiceOver_MessageContextSend
|
||||
let mediaRecordingAccessibilityArea: AccessibilityAreaNode
|
||||
@ -2463,7 +2490,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
self.slowmodePlaceholderNode?.isHidden = true
|
||||
}
|
||||
|
||||
var nextButtonTopRight = CGPoint(x: hideOffset.x + width - rightInset - textFieldInsets.right - accessoryButtonInset, y: hideOffset.y + panelHeight - textFieldInsets.bottom - minimalInputHeight)
|
||||
var nextButtonTopRight = CGPoint(x: hideOffset.x + width - rightInset - textFieldInsets.right - accessoryButtonInset - rightSlowModeInset, y: hideOffset.y + panelHeight - textFieldInsets.bottom - minimalInputHeight)
|
||||
for (item, button) in self.accessoryItemButtons.reversed() {
|
||||
let buttonSize = CGSize(width: button.buttonWidth, height: minimalInputHeight)
|
||||
button.updateLayout(item: item, size: buttonSize)
|
||||
@ -2736,6 +2763,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
return panelHeight
|
||||
}
|
||||
|
||||
@objc private func slowModeButtonPressed() {
|
||||
self.interfaceInteraction?.openBoostToUnrestrict()
|
||||
}
|
||||
|
||||
@objc private func viewOncePressed() {
|
||||
guard let context = self.context, let interfaceState = self.presentationInterfaceState else {
|
||||
return
|
||||
@ -3239,7 +3270,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
composeButtonsOffset = 44.0
|
||||
}
|
||||
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - self.leftMenuInset, maxHeight: maxHeight, metrics: metrics)
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - self.leftMenuInset - self.rightSlowModeInset, maxHeight: maxHeight, metrics: metrics)
|
||||
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
|
||||
var textFieldMinHeight: CGFloat = 33.0
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
@ -3544,7 +3575,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
}
|
||||
}
|
||||
|
||||
self.updateActionButtons(hasText: inputHasText, hideMicButton: hideMicButton, animated: animated)
|
||||
let _ = hideMicButton
|
||||
// self.updateActionButtons(hasText: inputHasText, hideMicButton: hideMicButton, animated: animated)
|
||||
self.updateTextHeight(animated: animated)
|
||||
}
|
||||
|
||||
@ -3605,7 +3637,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
|
||||
if (hasText || self.keepSendButtonEnabled && !mediaInputIsActive) {
|
||||
hideMicButton = true
|
||||
if self.actionButtons.sendContainerNode.alpha.isZero {
|
||||
|
||||
if self.actionButtons.sendContainerNode.alpha.isZero && self.rightSlowModeInset.isZero {
|
||||
self.actionButtons.sendContainerNode.alpha = 1.0
|
||||
self.actionButtons.sendButtonRadialStatusNode?.alpha = 1.0
|
||||
self.actionButtons.updateAccessibility()
|
||||
@ -3621,6 +3654,17 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.slowModeButton.alpha.isZero && self.rightSlowModeInset > 0.0 {
|
||||
self.slowModeButton.alpha = 1.0
|
||||
if animated {
|
||||
self.slowModeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||
if animateWithBounce {
|
||||
self.slowModeButton.layer.animateSpring(from: NSNumber(value: Float(0.1)), to: NSNumber(value: Float(1.0)), keyPath: "transform.scale", duration: 0.6)
|
||||
} else {
|
||||
self.slowModeButton.layer.animateScale(from: 0.2, to: 1.0, duration: 0.25)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !self.actionButtons.sendContainerNode.alpha.isZero {
|
||||
self.actionButtons.sendContainerNode.alpha = 0.0
|
||||
@ -3637,6 +3681,12 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
self.actionButtons.sendButtonRadialStatusNode?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
if !self.slowModeButton.alpha.isZero {
|
||||
self.slowModeButton.alpha = 0.0
|
||||
if animated {
|
||||
self.slowModeButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3694,7 +3744,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
|
||||
private func updateTextHeight(animated: Bool) {
|
||||
if let (width, leftInset, rightInset, _, additionalSideInsets, maxHeight, metrics, _, _) = self.validLayout {
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - additionalSideInsets.right - self.leftMenuInset, maxHeight: maxHeight, metrics: metrics)
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - additionalSideInsets.right - self.leftMenuInset - self.rightSlowModeInset, maxHeight: maxHeight, metrics: metrics)
|
||||
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
|
||||
if !self.bounds.size.height.isEqual(to: panelHeight) {
|
||||
self.updateHeight(animated)
|
||||
@ -4620,3 +4670,97 @@ private final class MenuIconNode: ManagedAnimationNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func generateClearImage(color: UIColor) -> UIImage? {
|
||||
return generateImage(CGSize(width: 17.0, height: 17.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(color.cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||
context.setBlendMode(.copy)
|
||||
context.setStrokeColor(UIColor.clear.cgColor)
|
||||
context.setLineCap(.round)
|
||||
context.setLineWidth(1.66)
|
||||
context.move(to: CGPoint(x: 6.0, y: 6.0))
|
||||
context.addLine(to: CGPoint(x: 11.0, y: 11.0))
|
||||
context.strokePath()
|
||||
context.move(to: CGPoint(x: size.width - 6.0, y: 6.0))
|
||||
context.addLine(to: CGPoint(x: size.width - 11.0, y: 11.0))
|
||||
context.strokePath()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
||||
let backgroundNode: ASImageNode
|
||||
let textNode: ImmediateAnimatedCountLabelNode
|
||||
let iconNode: ASImageNode
|
||||
|
||||
private var updateTimer: SwiftSignalKit.Timer?
|
||||
|
||||
var requestUpdate: () -> Void = {}
|
||||
|
||||
override init(pointerStyle: PointerStyle? = nil) {
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.clipsToBounds = true
|
||||
self.backgroundNode.image = generateGradientImage(size: CGSize(width: 100.0, height: 2.0), scale: 1.0, colors: [UIColor(rgb: 0x9076ff), UIColor(rgb: 0xbc6de8)], locations: [0.0, 1.0], direction: .horizontal)
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.displaysAsynchronously = false
|
||||
self.iconNode.image = generateClearImage(color: .white)
|
||||
|
||||
self.textNode = ImmediateAnimatedCountLabelNode()
|
||||
self.textNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init(pointerStyle: pointerStyle)
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.textNode)
|
||||
}
|
||||
|
||||
func update(size: CGSize, interfaceState: ChatPresentationInterfaceState) -> CGSize {
|
||||
var text = ""
|
||||
if let slowmodeState = interfaceState.slowmodeState, case let .timestamp(validUntilTimestamp) = slowmodeState.variant {
|
||||
let timestamp = CGFloat(Date().timeIntervalSince1970)
|
||||
let relativeTimestamp = CGFloat(validUntilTimestamp) - timestamp
|
||||
text = stringForDuration(Int32(relativeTimestamp))
|
||||
|
||||
self.updateTimer?.invalidate()
|
||||
self.updateTimer = SwiftSignalKit.Timer(timeout: 1.0 / 60.0, repeat: false, completion: { [weak self] in
|
||||
self?.requestUpdate()
|
||||
}, queue: .mainQueue())
|
||||
self.updateTimer?.start()
|
||||
} else {
|
||||
self.updateTimer?.invalidate()
|
||||
self.updateTimer = nil
|
||||
}
|
||||
|
||||
let font = Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers])
|
||||
let textColor = UIColor.white
|
||||
|
||||
var segments: [AnimatedCountLabelNode.Segment] = []
|
||||
var textCount = 0
|
||||
|
||||
for char in text {
|
||||
if let intValue = Int(String(char)) {
|
||||
segments.append(.number(intValue, NSAttributedString(string: String(char), font: font, textColor: textColor)))
|
||||
} else {
|
||||
segments.append(.text(textCount, NSAttributedString(string: String(char), font: font, textColor: textColor)))
|
||||
textCount += 1
|
||||
}
|
||||
}
|
||||
self.textNode.segments = segments
|
||||
|
||||
let textSize = self.textNode.updateLayout(size: CGSize(width: 200.0, height: 100.0), animated: true)
|
||||
let totalSize = CGSize(width: textSize.width > 0.0 ? textSize.width + 38.0 : 33.0, height: 33.0)
|
||||
|
||||
self.backgroundNode.frame = CGRect(origin: .zero, size: totalSize)
|
||||
self.backgroundNode.cornerRadius = totalSize.height / 2.0
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: 9.0, y: floorToScreenPixels((totalSize.height - textSize.height) / 2.0)), size: textSize)
|
||||
if let icon = self.iconNode.image {
|
||||
self.iconNode.frame = CGRect(origin: CGPoint(x: totalSize.width - icon.size.width - 7.0, y: floorToScreenPixels((totalSize.height - icon.size.height) / 2.0)), size: icon.size)
|
||||
}
|
||||
return totalSize
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user