mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-02 04:38:33 +00:00
Merge commit 'ba24da05932f634d5d19e647fb3de0d9105dbd7c'
This commit is contained in:
commit
31260e710b
@ -11307,3 +11307,11 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Story.GroupCommentingRestrictedPlaceholder" = "Comments restricted. Boost the group to unlock.";
|
"Story.GroupCommentingRestrictedPlaceholder" = "Comments restricted. Boost the group to unlock.";
|
||||||
"Story.GroupCommentingRestrictedPlaceholderAction" = "Learn More...";
|
"Story.GroupCommentingRestrictedPlaceholderAction" = "Learn More...";
|
||||||
|
|
||||||
|
"GroupBoost.Table.Group.VoiceToText" = "Voice-to-Text Conversion";
|
||||||
|
"GroupBoost.Table.Group.EmojiPack" = "Custom Emojipack";
|
||||||
|
|
||||||
|
"ChannelBoost.Header.Boost" = "boost";
|
||||||
|
"ChannelBoost.Header.Giveaway" = "giveaway";
|
||||||
|
"ChannelBoost.Header.Features" = "features";
|
||||||
|
|
||||||
|
|||||||
@ -983,6 +983,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}, openPremiumGift: {
|
}, openPremiumGift: {
|
||||||
}, openPremiumRequiredForMessaging: {
|
}, openPremiumRequiredForMessaging: {
|
||||||
}, openBoostToUnrestrict: {
|
}, openBoostToUnrestrict: {
|
||||||
|
}, updateVideoTrimRange: { _, _, _, _ in
|
||||||
}, updateHistoryFilter: { _ in
|
}, updateHistoryFilter: { _ in
|
||||||
}, updateDisplayHistoryFilterAsList: { _ in
|
}, updateDisplayHistoryFilterAsList: { _ in
|
||||||
}, requestLayout: { _ in
|
}, requestLayout: { _ in
|
||||||
|
|||||||
@ -277,13 +277,16 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
private struct Params: Equatable {
|
private struct Params: Equatable {
|
||||||
let peerId: EnginePeer.Id?
|
let peerId: EnginePeer.Id?
|
||||||
let resourceId: String?
|
let resourceId: String?
|
||||||
|
let clipStyle: AvatarNodeClipStyle
|
||||||
|
|
||||||
init(
|
init(
|
||||||
peerId: EnginePeer.Id?,
|
peerId: EnginePeer.Id?,
|
||||||
resourceId: String?
|
resourceId: String?,
|
||||||
|
clipStyle: AvatarNodeClipStyle
|
||||||
) {
|
) {
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.resourceId = resourceId
|
self.resourceId = resourceId
|
||||||
|
self.clipStyle = clipStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +318,15 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
private var params: Params?
|
private var params: Params?
|
||||||
private var loadDisposable: Disposable?
|
private var loadDisposable: Disposable?
|
||||||
|
|
||||||
|
var clipStyle: AvatarNodeClipStyle {
|
||||||
|
if let params = self.params {
|
||||||
|
return params.clipStyle
|
||||||
|
} else if case let .peerAvatar(_, _, _, _, clipStyle) = self.state {
|
||||||
|
return clipStyle
|
||||||
|
}
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
|
||||||
public var badgeView: AvatarBadgeView? {
|
public var badgeView: AvatarBadgeView? {
|
||||||
didSet {
|
didSet {
|
||||||
if self.badgeView !== oldValue {
|
if self.badgeView !== oldValue {
|
||||||
@ -516,6 +528,7 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
} else if peer?.restrictionText(platform: "ios", contentSettings: contentSettings) == nil {
|
} else if peer?.restrictionText(platform: "ios", contentSettings: contentSettings) == nil {
|
||||||
representation = peer?.smallProfileImage
|
representation = peer?.smallProfileImage
|
||||||
}
|
}
|
||||||
|
|
||||||
let updatedState: AvatarNodeState = .peerAvatar(peer?.id ?? EnginePeer.Id(0), peer?.nameColor, peer?.displayLetters ?? [], representation, clipStyle)
|
let updatedState: AvatarNodeState = .peerAvatar(peer?.id ?? EnginePeer.Id(0), peer?.nameColor, peer?.displayLetters ?? [], representation, clipStyle)
|
||||||
if updatedState != self.state || overrideImage != self.overrideImage || theme !== self.theme {
|
if updatedState != self.state || overrideImage != self.overrideImage || theme !== self.theme {
|
||||||
self.state = updatedState
|
self.state = updatedState
|
||||||
@ -599,7 +612,8 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
let smallProfileImage = peer?.smallProfileImage
|
let smallProfileImage = peer?.smallProfileImage
|
||||||
let params = Params(
|
let params = Params(
|
||||||
peerId: peer?.id,
|
peerId: peer?.id,
|
||||||
resourceId: smallProfileImage?.resource.id.stringRepresentation
|
resourceId: smallProfileImage?.resource.id.stringRepresentation,
|
||||||
|
clipStyle: clipStyle
|
||||||
)
|
)
|
||||||
if self.params == params {
|
if self.params == params {
|
||||||
return
|
return
|
||||||
@ -689,6 +703,7 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
} else if peer?.restrictionText(platform: "ios", contentSettings: genericContext.currentContentSettings.with { $0 }) == nil {
|
} else if peer?.restrictionText(platform: "ios", contentSettings: genericContext.currentContentSettings.with { $0 }) == nil {
|
||||||
representation = peer?.smallProfileImage
|
representation = peer?.smallProfileImage
|
||||||
}
|
}
|
||||||
|
|
||||||
let updatedState: AvatarNodeState = .peerAvatar(peer?.id ?? EnginePeer.Id(0), peer?.nameColor, peer?.displayLetters ?? [], representation, clipStyle)
|
let updatedState: AvatarNodeState = .peerAvatar(peer?.id ?? EnginePeer.Id(0), peer?.nameColor, peer?.displayLetters ?? [], representation, clipStyle)
|
||||||
if updatedState != self.state || overrideImage != self.overrideImage || theme !== self.theme {
|
if updatedState != self.state || overrideImage != self.overrideImage || theme !== self.theme {
|
||||||
self.state = updatedState
|
self.state = updatedState
|
||||||
@ -1212,15 +1227,18 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
public var colors: Colors
|
public var colors: Colors
|
||||||
public var lineWidth: CGFloat
|
public var lineWidth: CGFloat
|
||||||
public var inactiveLineWidth: CGFloat
|
public var inactiveLineWidth: CGFloat
|
||||||
|
public var forceRoundedRect: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
colors: Colors,
|
colors: Colors,
|
||||||
lineWidth: CGFloat,
|
lineWidth: CGFloat,
|
||||||
inactiveLineWidth: CGFloat
|
inactiveLineWidth: CGFloat,
|
||||||
|
forceRoundedRect: Bool = false
|
||||||
) {
|
) {
|
||||||
self.colors = colors
|
self.colors = colors
|
||||||
self.lineWidth = lineWidth
|
self.lineWidth = lineWidth
|
||||||
self.inactiveLineWidth = inactiveLineWidth
|
self.inactiveLineWidth = inactiveLineWidth
|
||||||
|
self.forceRoundedRect = forceRoundedRect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1274,7 +1292,8 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
totalCount: storyStats.totalCount,
|
totalCount: storyStats.totalCount,
|
||||||
unseenCount: storyStats.unseenCount
|
unseenCount: storyStats.unseenCount
|
||||||
),
|
),
|
||||||
progress: mappedProgress
|
progress: mappedProgress,
|
||||||
|
isRoundedRect: self.contentNode.clipStyle == .roundedRect || storyPresentationParams.forceRoundedRect
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: indicatorSize
|
containerSize: indicatorSize
|
||||||
|
|||||||
@ -2905,14 +2905,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
})))
|
})))
|
||||||
} else if case let .channel(channel) = peer {
|
} else if case let .channel(channel) = peer {
|
||||||
let openTitle: String
|
let openTitle: String
|
||||||
|
let openIcon: String
|
||||||
switch channel.info {
|
switch channel.info {
|
||||||
case .broadcast:
|
case .broadcast:
|
||||||
openTitle = self.presentationData.strings.ChatList_ContextOpenChannel
|
openTitle = self.presentationData.strings.ChatList_ContextOpenChannel
|
||||||
|
openIcon = "Chat/Context Menu/Channels"
|
||||||
case .group:
|
case .group:
|
||||||
openTitle = self.presentationData.strings.ChatList_ContextOpenGroup
|
openTitle = self.presentationData.strings.ChatList_ContextOpenGroup
|
||||||
|
openIcon = "Chat/Context Menu/Groups"
|
||||||
}
|
}
|
||||||
items.append(.action(ContextMenuActionItem(text: openTitle, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: openTitle, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Channels"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: openIcon), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { [weak self] c, _ in
|
}, action: { [weak self] c, _ in
|
||||||
c.dismiss(completion: {
|
c.dismiss(completion: {
|
||||||
guard let self else {
|
guard let self else {
|
||||||
|
|||||||
@ -176,6 +176,7 @@ public final class ChatPanelInterfaceInteraction {
|
|||||||
public let updateHistoryFilter: ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void
|
public let updateHistoryFilter: ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void
|
||||||
public let updateDisplayHistoryFilterAsList: (Bool) -> Void
|
public let updateDisplayHistoryFilterAsList: (Bool) -> Void
|
||||||
public let openBoostToUnrestrict: () -> Void
|
public let openBoostToUnrestrict: () -> Void
|
||||||
|
public let updateVideoTrimRange: (Double, Double, Bool, Bool) -> Void
|
||||||
public let requestLayout: (ContainedViewLayoutTransition) -> Void
|
public let requestLayout: (ContainedViewLayoutTransition) -> Void
|
||||||
public let chatController: () -> ViewController?
|
public let chatController: () -> ViewController?
|
||||||
public let statuses: ChatPanelInterfaceInteractionStatuses?
|
public let statuses: ChatPanelInterfaceInteractionStatuses?
|
||||||
@ -286,6 +287,7 @@ public final class ChatPanelInterfaceInteraction {
|
|||||||
openPremiumGift: @escaping () -> Void,
|
openPremiumGift: @escaping () -> Void,
|
||||||
openPremiumRequiredForMessaging: @escaping () -> Void,
|
openPremiumRequiredForMessaging: @escaping () -> Void,
|
||||||
openBoostToUnrestrict: @escaping () -> Void,
|
openBoostToUnrestrict: @escaping () -> Void,
|
||||||
|
updateVideoTrimRange: @escaping (Double, Double, Bool, Bool) -> Void,
|
||||||
updateHistoryFilter: @escaping ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void,
|
updateHistoryFilter: @escaping ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void,
|
||||||
updateDisplayHistoryFilterAsList: @escaping (Bool) -> Void,
|
updateDisplayHistoryFilterAsList: @escaping (Bool) -> Void,
|
||||||
requestLayout: @escaping (ContainedViewLayoutTransition) -> Void,
|
requestLayout: @escaping (ContainedViewLayoutTransition) -> Void,
|
||||||
@ -397,6 +399,7 @@ public final class ChatPanelInterfaceInteraction {
|
|||||||
self.openPremiumGift = openPremiumGift
|
self.openPremiumGift = openPremiumGift
|
||||||
self.openPremiumRequiredForMessaging = openPremiumRequiredForMessaging
|
self.openPremiumRequiredForMessaging = openPremiumRequiredForMessaging
|
||||||
self.openBoostToUnrestrict = openBoostToUnrestrict
|
self.openBoostToUnrestrict = openBoostToUnrestrict
|
||||||
|
self.updateVideoTrimRange = updateVideoTrimRange
|
||||||
self.updateHistoryFilter = updateHistoryFilter
|
self.updateHistoryFilter = updateHistoryFilter
|
||||||
self.updateDisplayHistoryFilterAsList = updateDisplayHistoryFilterAsList
|
self.updateDisplayHistoryFilterAsList = updateDisplayHistoryFilterAsList
|
||||||
self.requestLayout = requestLayout
|
self.requestLayout = requestLayout
|
||||||
@ -516,6 +519,7 @@ public final class ChatPanelInterfaceInteraction {
|
|||||||
}, openPremiumGift: {
|
}, openPremiumGift: {
|
||||||
}, openPremiumRequiredForMessaging: {
|
}, openPremiumRequiredForMessaging: {
|
||||||
}, openBoostToUnrestrict: {
|
}, openBoostToUnrestrict: {
|
||||||
|
}, updateVideoTrimRange: { _, _, _, _ in
|
||||||
}, updateHistoryFilter: { _ in
|
}, updateHistoryFilter: { _ in
|
||||||
}, updateDisplayHistoryFilterAsList: { _ in
|
}, updateDisplayHistoryFilterAsList: { _ in
|
||||||
}, requestLayout: { _ in
|
}, requestLayout: { _ in
|
||||||
|
|||||||
@ -271,9 +271,9 @@ private final class LevelSectionComponent: CombinedComponent {
|
|||||||
case .customWallpaper:
|
case .customWallpaper:
|
||||||
return isGroup ? strings.ChannelBoost_Table_Group_CustomWallpaper : strings.ChannelBoost_Table_CustomWallpaper
|
return isGroup ? strings.ChannelBoost_Table_Group_CustomWallpaper : strings.ChannelBoost_Table_CustomWallpaper
|
||||||
case .audioTranscription:
|
case .audioTranscription:
|
||||||
return "Voice-to-Text Conversion"
|
return strings.GroupBoost_Table_Group_VoiceToText
|
||||||
case .emojiPack:
|
case .emojiPack:
|
||||||
return "Custom Emojipack"
|
return strings.GroupBoost_Table_Group_EmojiPack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2234,12 +2234,12 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
self.myBoostCount += 1
|
self.myBoostCount += 1
|
||||||
|
|
||||||
let _ = (context.engine.peers.applyChannelBoost(peerId: peerId, slots: [availableBoost.slot])
|
let _ = (context.engine.peers.applyChannelBoost(peerId: peerId, slots: [availableBoost.slot])
|
||||||
|> deliverOnMainQueue).startStandalone(completed: { [weak self] in
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] myBoostStatus in
|
||||||
self?.updatedState.set(context.engine.peers.getChannelBoostStatus(peerId: peerId)
|
self?.updatedState.set(context.engine.peers.getChannelBoostStatus(peerId: peerId)
|
||||||
|> beforeNext { [weak self] status in
|
|> beforeNext { [weak self] boostStatus in
|
||||||
if let self, let status {
|
if let self, let boostStatus, let myBoostStatus {
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
self.controller?.boostStatusUpdated(status)
|
self.controller?.boostStatusUpdated(boostStatus, myBoostStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2293,8 +2293,8 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
).startStandalone(next: { boostStatus, myBoostStatus in
|
).startStandalone(next: { boostStatus, myBoostStatus in
|
||||||
dismissReplaceImpl?()
|
dismissReplaceImpl?()
|
||||||
|
|
||||||
if let boostStatus {
|
if let boostStatus, let myBoostStatus {
|
||||||
boostStatusUpdated(boostStatus)
|
boostStatusUpdated(boostStatus, myBoostStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
let levelsController = PremiumBoostLevelsScreen(
|
let levelsController = PremiumBoostLevelsScreen(
|
||||||
@ -2466,7 +2466,7 @@ public class PremiumBoostLevelsScreen: ViewController {
|
|||||||
|
|
||||||
private var currentLayout: ContainerViewLayout?
|
private var currentLayout: ContainerViewLayout?
|
||||||
|
|
||||||
public var boostStatusUpdated: (ChannelBoostStatus) -> Void = { _ in }
|
public var boostStatusUpdated: (ChannelBoostStatus, MyBoostStatus) -> Void = { _, _ in }
|
||||||
public var disposed: () -> Void = {}
|
public var disposed: () -> Void = {}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
|||||||
@ -399,7 +399,7 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
BoostButtonComponent(
|
BoostButtonComponent(
|
||||||
iconName: "Premium/Boosts/Boost",
|
iconName: "Premium/Boosts/Boost",
|
||||||
title: "boost"
|
title: component.strings.ChannelBoost_Header_Boost
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
@ -419,7 +419,7 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
BoostButtonComponent(
|
BoostButtonComponent(
|
||||||
iconName: "Premium/Boosts/Giveaway",
|
iconName: "Premium/Boosts/Giveaway",
|
||||||
title: "giveaway"
|
title: component.strings.ChannelBoost_Header_Giveaway
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
@ -439,7 +439,7 @@ private final class BoostHeaderComponent: CombinedComponent {
|
|||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
BoostButtonComponent(
|
BoostButtonComponent(
|
||||||
iconName: "Premium/Boosts/Features",
|
iconName: "Premium/Boosts/Features",
|
||||||
title: "features"
|
title: component.strings.ChannelBoost_Header_Features
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
|
|||||||
@ -1525,7 +1525,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
|||||||
controller?.push(giveawayController)
|
controller?.push(giveawayController)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
boostController.boostStatusUpdated = { boostStatus in
|
boostController.boostStatusUpdated = { boostStatus, _ in
|
||||||
boostDataPromise.set(.single(boostStatus))
|
boostDataPromise.set(.single(boostStatus))
|
||||||
}
|
}
|
||||||
controller?.push(boostController)
|
controller?.push(boostController)
|
||||||
|
|||||||
@ -169,6 +169,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
|
|||||||
}, openPremiumGift: {
|
}, openPremiumGift: {
|
||||||
}, openPremiumRequiredForMessaging: {
|
}, openPremiumRequiredForMessaging: {
|
||||||
}, openBoostToUnrestrict: {
|
}, openBoostToUnrestrict: {
|
||||||
|
}, updateVideoTrimRange: { _, _, _, _ in
|
||||||
}, updateHistoryFilter: { _ in
|
}, updateHistoryFilter: { _ in
|
||||||
}, updateDisplayHistoryFilterAsList: { _ in
|
}, updateDisplayHistoryFilterAsList: { _ in
|
||||||
}, requestLayout: { _ in
|
}, requestLayout: { _ in
|
||||||
|
|||||||
@ -126,10 +126,17 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
|||||||
progress: storyProgress
|
progress: storyProgress
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isForum = false
|
||||||
|
if let peer, let channel = peer as? TelegramChannel, channel.isForum {
|
||||||
|
isForum = true
|
||||||
|
}
|
||||||
|
|
||||||
self.avatarNode.setStoryStats(storyStats: storyStats, presentationParams: AvatarNode.StoryPresentationParams(
|
self.avatarNode.setStoryStats(storyStats: storyStats, presentationParams: AvatarNode.StoryPresentationParams(
|
||||||
colors: colors,
|
colors: colors,
|
||||||
lineWidth: 3.0,
|
lineWidth: 3.0,
|
||||||
inactiveLineWidth: 1.5
|
inactiveLineWidth: 1.5,
|
||||||
|
forceRoundedRect: isForum
|
||||||
), transition: Transition(transition))
|
), transition: Transition(transition))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -419,6 +419,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
|||||||
}, openPremiumGift: {
|
}, openPremiumGift: {
|
||||||
}, openPremiumRequiredForMessaging: {
|
}, openPremiumRequiredForMessaging: {
|
||||||
}, openBoostToUnrestrict: {
|
}, openBoostToUnrestrict: {
|
||||||
|
}, updateVideoTrimRange: { _, _, _, _ in
|
||||||
}, updateHistoryFilter: { _ in
|
}, updateHistoryFilter: { _ in
|
||||||
}, updateDisplayHistoryFilterAsList: { _ in
|
}, updateDisplayHistoryFilterAsList: { _ in
|
||||||
}, requestLayout: { _ in
|
}, requestLayout: { _ in
|
||||||
@ -1727,7 +1728,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let cachedData = data.cachedData as? CachedChannelData, cachedData.flags.contains(.canViewStats) {
|
if let cachedData = data.cachedData as? CachedChannelData, isCreator || cachedData.flags.contains(.canViewStats) {
|
||||||
items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStats, label: .none, text: presentationData.strings.Channel_Info_Stats, icon: UIImage(bundleImageName: "Chat/Info/StatsIcon"), action: {
|
items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStats, label: .none, text: presentationData.strings.Channel_Info_Stats, icon: UIImage(bundleImageName: "Chat/Info/StatsIcon"), action: {
|
||||||
interaction.openStats(false)
|
interaction.openStats(false)
|
||||||
}))
|
}))
|
||||||
|
|||||||
@ -733,6 +733,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||||||
}, openPremiumGift: {
|
}, openPremiumGift: {
|
||||||
}, openPremiumRequiredForMessaging: {
|
}, openPremiumRequiredForMessaging: {
|
||||||
}, openBoostToUnrestrict: {
|
}, openBoostToUnrestrict: {
|
||||||
|
}, updateVideoTrimRange: { _, _, _, _ in
|
||||||
}, updateHistoryFilter: { _ in
|
}, updateHistoryFilter: { _ in
|
||||||
}, updateDisplayHistoryFilterAsList: { _ in
|
}, updateDisplayHistoryFilterAsList: { _ in
|
||||||
}, requestLayout: { _ in
|
}, requestLayout: { _ in
|
||||||
|
|||||||
@ -304,6 +304,7 @@ final class ChannelAppearanceScreenComponent: Component {
|
|||||||
private var premiumConfiguration: PremiumConfiguration?
|
private var premiumConfiguration: PremiumConfiguration?
|
||||||
private var boostLevel: Int?
|
private var boostLevel: Int?
|
||||||
private var boostStatus: ChannelBoostStatus?
|
private var boostStatus: ChannelBoostStatus?
|
||||||
|
private var myBoostStatus: MyBoostStatus?
|
||||||
private var boostStatusDisposable: Disposable?
|
private var boostStatusDisposable: Disposable?
|
||||||
|
|
||||||
private var isApplyingSettings: Bool = false
|
private var isApplyingSettings: Bool = false
|
||||||
@ -656,6 +657,7 @@ final class ChannelAppearanceScreenComponent: Component {
|
|||||||
peerId: component.peerId,
|
peerId: component.peerId,
|
||||||
mode: .owner(subject: subject),
|
mode: .owner(subject: subject),
|
||||||
status: status,
|
status: status,
|
||||||
|
myBoostStatus: myBoostStatus,
|
||||||
openStats: { [weak self] in
|
openStats: { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -670,6 +672,14 @@ final class ChannelAppearanceScreenComponent: Component {
|
|||||||
self.environment?.controller()?.push(controller)
|
self.environment?.controller()?.push(controller)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
controller.boostStatusUpdated = { [weak self] boostStatus, myBoostStatus in
|
||||||
|
if let self {
|
||||||
|
self.boostStatus = boostStatus
|
||||||
|
self.boostLevel = boostStatus.level
|
||||||
|
self.myBoostStatus = myBoostStatus
|
||||||
|
self.state?.updated(transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
self.environment?.controller()?.push(controller)
|
self.environment?.controller()?.push(controller)
|
||||||
|
|
||||||
HapticFeedback().impact(.light)
|
HapticFeedback().impact(.light)
|
||||||
@ -924,13 +934,16 @@ final class ChannelAppearanceScreenComponent: Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if self.boostStatusDisposable == nil {
|
if self.boostStatusDisposable == nil {
|
||||||
self.boostStatusDisposable = (component.context.engine.peers.getChannelBoostStatus(peerId: component.peerId)
|
self.boostStatusDisposable = combineLatest(queue: Queue.mainQueue(),
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] boostStatus in
|
component.context.engine.peers.getChannelBoostStatus(peerId: component.peerId),
|
||||||
|
component.context.engine.peers.getMyBoostStatus()
|
||||||
|
).start(next: { [weak self] boostStatus, myBoostStatus in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.boostLevel = boostStatus?.level
|
self.boostLevel = boostStatus?.level
|
||||||
self.boostStatus = boostStatus
|
self.boostStatus = boostStatus
|
||||||
|
self.myBoostStatus = myBoostStatus
|
||||||
|
|
||||||
if !self.isUpdating {
|
if !self.isUpdating {
|
||||||
self.state?.updated(transition: .immediate)
|
self.state?.updated(transition: .immediate)
|
||||||
|
|||||||
@ -50,6 +50,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
public let inactiveLineWidth: CGFloat
|
public let inactiveLineWidth: CGFloat
|
||||||
public let counters: Counters?
|
public let counters: Counters?
|
||||||
public let progress: Progress?
|
public let progress: Progress?
|
||||||
|
public let isRoundedRect: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
hasUnseen: Bool,
|
hasUnseen: Bool,
|
||||||
@ -58,7 +59,8 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
activeLineWidth: CGFloat,
|
activeLineWidth: CGFloat,
|
||||||
inactiveLineWidth: CGFloat,
|
inactiveLineWidth: CGFloat,
|
||||||
counters: Counters?,
|
counters: Counters?,
|
||||||
progress: Progress? = nil
|
progress: Progress? = nil,
|
||||||
|
isRoundedRect: Bool = false
|
||||||
) {
|
) {
|
||||||
self.hasUnseen = hasUnseen
|
self.hasUnseen = hasUnseen
|
||||||
self.hasUnseenCloseFriendsItems = hasUnseenCloseFriendsItems
|
self.hasUnseenCloseFriendsItems = hasUnseenCloseFriendsItems
|
||||||
@ -67,6 +69,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
self.inactiveLineWidth = inactiveLineWidth
|
self.inactiveLineWidth = inactiveLineWidth
|
||||||
self.counters = counters
|
self.counters = counters
|
||||||
self.progress = progress
|
self.progress = progress
|
||||||
|
self.isRoundedRect = isRoundedRect
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: AvatarStoryIndicatorComponent, rhs: AvatarStoryIndicatorComponent) -> Bool {
|
public static func ==(lhs: AvatarStoryIndicatorComponent, rhs: AvatarStoryIndicatorComponent) -> Bool {
|
||||||
@ -91,6 +94,9 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
if lhs.progress != rhs.progress {
|
if lhs.progress != rhs.progress {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isRoundedRect != rhs.isRoundedRect {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +217,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(size: CGSize, radius: CGFloat, lineWidth: CGFloat, value: Value, transition: Transition) {
|
func update(size: CGSize, radius: CGFloat, isRoundedRect: Bool, lineWidth: CGFloat, value: Value, transition: Transition) {
|
||||||
let params = Params(
|
let params = Params(
|
||||||
size: size,
|
size: size,
|
||||||
lineWidth: lineWidth,
|
lineWidth: lineWidth,
|
||||||
@ -295,7 +301,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
|
|
||||||
var locations: [CGFloat] = [0.0, 1.0]
|
var locations: [CGFloat] = [0.0, 1.0]
|
||||||
|
|
||||||
if let counters = component.counters, counters.totalCount > 1 {
|
if let counters = component.counters, counters.totalCount > 1, !component.isRoundedRect {
|
||||||
let center = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
|
let center = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
|
||||||
let spacing: CGFloat = component.activeLineWidth * 2.0
|
let spacing: CGFloat = component.activeLineWidth * 2.0
|
||||||
let angularSpacing: CGFloat = spacing / radius
|
let angularSpacing: CGFloat = spacing / radius
|
||||||
@ -347,7 +353,11 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
let lineWidth: CGFloat = component.hasUnseen ? component.activeLineWidth : component.inactiveLineWidth
|
let lineWidth: CGFloat = component.hasUnseen ? component.activeLineWidth : component.inactiveLineWidth
|
||||||
context.setLineWidth(lineWidth)
|
context.setLineWidth(lineWidth)
|
||||||
|
if component.isRoundedRect {
|
||||||
|
context.addPath(UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: size.width * 0.5 - diameter * 0.5, y: size.height * 0.5 - diameter * 0.5), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5), cornerRadius: floor(diameter * 0.25)).cgPath)
|
||||||
|
} else {
|
||||||
context.addEllipse(in: CGRect(origin: CGPoint(x: size.width * 0.5 - diameter * 0.5, y: size.height * 0.5 - diameter * 0.5), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
context.addEllipse(in: CGRect(origin: CGPoint(x: size.width * 0.5 - diameter * 0.5, y: size.height * 0.5 - diameter * 0.5), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
||||||
|
}
|
||||||
|
|
||||||
context.replacePathWithStrokedPath()
|
context.replacePathWithStrokedPath()
|
||||||
context.clip()
|
context.clip()
|
||||||
@ -369,7 +379,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
transition.setFrame(view: self.indicatorView, frame: indicatorFrame)
|
transition.setFrame(view: self.indicatorView, frame: indicatorFrame)
|
||||||
|
|
||||||
let progressTransition = Transition(animation: .curve(duration: 0.3, curve: .easeInOut))
|
let progressTransition = Transition(animation: .curve(duration: 0.3, curve: .easeInOut))
|
||||||
if let progress = component.progress {
|
if let progress = component.progress, !component.isRoundedRect {
|
||||||
let colorLayer: SimpleGradientLayer
|
let colorLayer: SimpleGradientLayer
|
||||||
if let current = self.colorLayer {
|
if let current = self.colorLayer {
|
||||||
colorLayer = current
|
colorLayer = current
|
||||||
@ -415,7 +425,7 @@ public final class AvatarStoryIndicatorComponent: Component {
|
|||||||
mappedProgress = .progress(value)
|
mappedProgress = .progress(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
progressLayer.update(size: indicatorFrame.size, radius: radius, lineWidth: lineWidth, value: mappedProgress, transition: .immediate)
|
progressLayer.update(size: indicatorFrame.size, radius: radius, isRoundedRect: component.isRoundedRect, lineWidth: lineWidth, value: mappedProgress, transition: .immediate)
|
||||||
} else {
|
} else {
|
||||||
progressTransition.setAlpha(view: self.indicatorView, alpha: 1.0)
|
progressTransition.setAlpha(view: self.indicatorView, alpha: 1.0)
|
||||||
|
|
||||||
|
|||||||
@ -966,7 +966,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
|
|
||||||
if let controller = self.controller, let layout = self.validLayout {
|
if let controller = self.controller, let layout = self.validLayout {
|
||||||
let insets = layout.insets(options: .input)
|
let insets = layout.insets(options: .input)
|
||||||
if point.y > layout.size.height - insets.bottom - controller.inputPanelFrame.height {
|
if point.y > layout.size.height - insets.bottom - controller.inputPanelFrame.0.height {
|
||||||
if layout.metrics.isTablet {
|
if layout.metrics.isTablet {
|
||||||
if point.x < layout.size.width * 0.33 {
|
if point.x < layout.size.width * 0.33 {
|
||||||
return result
|
return result
|
||||||
@ -1111,9 +1111,9 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
self.didAppear()
|
self.didAppear()
|
||||||
}
|
}
|
||||||
|
|
||||||
var backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: controller.inputPanelFrame.minY))
|
var backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: controller.inputPanelFrame.0.minY))
|
||||||
if backgroundFrame.maxY < layout.size.height - 100.0 && (layout.inputHeight ?? 0.0).isZero {
|
if backgroundFrame.maxY < layout.size.height - 100.0 && (layout.inputHeight ?? 0.0).isZero && !controller.inputPanelFrame.1 {
|
||||||
backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: layout.size.height - layout.intrinsicInsets.bottom - controller.inputPanelFrame.height))
|
backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: layout.size.height - layout.intrinsicInsets.bottom - controller.inputPanelFrame.0.height))
|
||||||
}
|
}
|
||||||
|
|
||||||
transition.setPosition(view: self.backgroundView, position: backgroundFrame.center)
|
transition.setPosition(view: self.backgroundView, position: backgroundFrame.center)
|
||||||
@ -1266,7 +1266,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
private let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||||
private let inputPanelFrame: CGRect
|
private let inputPanelFrame: (CGRect, Bool)
|
||||||
fileprivate var allowLiveUpload: Bool
|
fileprivate var allowLiveUpload: Bool
|
||||||
fileprivate var viewOnceAvailable: Bool
|
fileprivate var viewOnceAvailable: Bool
|
||||||
|
|
||||||
@ -1417,7 +1417,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
|
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
|
||||||
allowLiveUpload: Bool,
|
allowLiveUpload: Bool,
|
||||||
viewOnceAvailable: Bool,
|
viewOnceAvailable: Bool,
|
||||||
inputPanelFrame: CGRect,
|
inputPanelFrame: (CGRect, Bool),
|
||||||
chatNode: ASDisplayNode?,
|
chatNode: ASDisplayNode?,
|
||||||
completion: @escaping (EnqueueMessage?, Bool?, Int32?) -> Void
|
completion: @escaping (EnqueueMessage?, Bool?, Int32?) -> Void
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -11136,6 +11136,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
)
|
)
|
||||||
self.push(boostController)
|
self.push(boostController)
|
||||||
})
|
})
|
||||||
|
}, updateVideoTrimRange: { [weak self] start, end, updatedEnd, apply in
|
||||||
|
if let videoRecorder = self?.videoRecorderValue {
|
||||||
|
videoRecorder.updateTrimRange(start: start, end: end, updatedEnd: updatedEnd, apply: apply)
|
||||||
|
}
|
||||||
}, updateHistoryFilter: { [weak self] update in
|
}, updateHistoryFilter: { [weak self] update in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -14128,7 +14132,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
updatedPresentationData: self.updatedPresentationData,
|
updatedPresentationData: self.updatedPresentationData,
|
||||||
allowLiveUpload: peerId.namespace != Namespaces.Peer.SecretChat,
|
allowLiveUpload: peerId.namespace != Namespaces.Peer.SecretChat,
|
||||||
viewOnceAvailable: !isScheduledMessages && peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId && !isBot,
|
viewOnceAvailable: !isScheduledMessages && peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId && !isBot,
|
||||||
inputPanelFrame: currentInputPanelFrame,
|
inputPanelFrame: (currentInputPanelFrame, self.chatDisplayNode.inputNode != nil),
|
||||||
chatNode: self.chatDisplayNode.historyNode,
|
chatNode: self.chatDisplayNode.historyNode,
|
||||||
completion: { [weak self] message, silentPosting, scheduleTime in
|
completion: { [weak self] message, silentPosting, scheduleTime in
|
||||||
guard let self, let videoController = self.videoRecorderValue else {
|
guard let self, let videoController = self.videoRecorderValue else {
|
||||||
|
|||||||
@ -188,7 +188,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
private let inputContextOverTextPanelContainer: ChatControllerTitlePanelNodeContainer
|
private let inputContextOverTextPanelContainer: ChatControllerTitlePanelNodeContainer
|
||||||
private var overlayContextPanelNode: ChatInputContextPanelNode?
|
private var overlayContextPanelNode: ChatInputContextPanelNode?
|
||||||
|
|
||||||
private var inputNode: ChatInputNode?
|
private(set) var inputNode: ChatInputNode?
|
||||||
private var disappearingNode: ChatInputNode?
|
private var disappearingNode: ChatInputNode?
|
||||||
|
|
||||||
private(set) var textInputPanelNode: ChatTextInputPanelNode?
|
private(set) var textInputPanelNode: ChatTextInputPanelNode?
|
||||||
|
|||||||
@ -328,8 +328,10 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
positionUpdated: { _, _ in },
|
positionUpdated: { _, _ in },
|
||||||
trackTrimUpdated: { _, start, end, updatedEnd, apply in
|
trackTrimUpdated: { [weak self] _, start, end, updatedEnd, apply in
|
||||||
// video.control.updateTrimRange(start, end, updatedEnd, apply)
|
if let self {
|
||||||
|
self.interfaceInteraction?.updateVideoTrimRange(start, end, updatedEnd, apply)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
trackOffsetUpdated: { _, _, _ in },
|
trackOffsetUpdated: { _, _, _ in },
|
||||||
trackLongPressed: { _, _ in }
|
trackLongPressed: { _, _ in }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user