Group boosts

This commit is contained in:
Ilya Laktyushin 2024-02-07 17:03:02 +04:00
parent 9d2fb9f8e3
commit a8cff5c5e0
3 changed files with 85 additions and 67 deletions

View File

@ -11207,4 +11207,10 @@ Sorry for the inconvenience.";
"GroupBoost.CustomWallpaper" = "Set Custom Group Wallpaper"; "GroupBoost.CustomWallpaper" = "Set Custom Group Wallpaper";
"GroupBoost.EnableCustomWallpaperLevelText" = "Your group needs **Level %1$@** to set custom group wallpaper."; "GroupBoost.EnableCustomWallpaperLevelText" = "Your group needs **Level %1$@** to set custom group wallpaper.";
"GroupBoost.EmojiPack" = "Set Group Emoji Pack";
"GroupBoost.EnableEmojiPackLevelText" = "Your group needs **Level %1$@** to set emoji pack."; "GroupBoost.EnableEmojiPackLevelText" = "Your group needs **Level %1$@** to set emoji pack.";
"GroupBoost.AudioTranscription" = "Audio Transcription";
"GroupBoost.AdditionalFeatures" = "Additional Features";
"GroupBoost.AdditionalFeaturesText" = "By gaining **boosts**, your group reaches higher levels and unlocks more features.";

View File

@ -88,6 +88,7 @@ public class PeerNameColors: Equatable {
profileStoryDarkColors: [:], profileStoryDarkColors: [:],
profileDisplayOrder: [], profileDisplayOrder: [],
nameColorsChannelMinRequiredBoostLevel: [:], nameColorsChannelMinRequiredBoostLevel: [:],
profileColorsChannelMinRequiredBoostLevel: [:],
profileColorsGroupMinRequiredBoostLevel: [:] profileColorsGroupMinRequiredBoostLevel: [:]
) )
} }
@ -105,6 +106,7 @@ public class PeerNameColors: Equatable {
public let profileDisplayOrder: [Int32] public let profileDisplayOrder: [Int32]
public let nameColorsChannelMinRequiredBoostLevel: [Int32: Int32] public let nameColorsChannelMinRequiredBoostLevel: [Int32: Int32]
public let profileColorsChannelMinRequiredBoostLevel: [Int32: Int32]
public let profileColorsGroupMinRequiredBoostLevel: [Int32: Int32] public let profileColorsGroupMinRequiredBoostLevel: [Int32: Int32]
public func get(_ color: PeerNameColor, dark: Bool = false) -> Colors { public func get(_ color: PeerNameColor, dark: Bool = false) -> Colors {
@ -158,6 +160,7 @@ public class PeerNameColors: Equatable {
profileStoryDarkColors: [Int32: Colors], profileStoryDarkColors: [Int32: Colors],
profileDisplayOrder: [Int32], profileDisplayOrder: [Int32],
nameColorsChannelMinRequiredBoostLevel: [Int32: Int32], nameColorsChannelMinRequiredBoostLevel: [Int32: Int32],
profileColorsChannelMinRequiredBoostLevel: [Int32: Int32],
profileColorsGroupMinRequiredBoostLevel: [Int32: Int32] profileColorsGroupMinRequiredBoostLevel: [Int32: Int32]
) { ) {
self.colors = colors self.colors = colors
@ -171,6 +174,7 @@ public class PeerNameColors: Equatable {
self.profileStoryDarkColors = profileStoryDarkColors self.profileStoryDarkColors = profileStoryDarkColors
self.profileDisplayOrder = profileDisplayOrder self.profileDisplayOrder = profileDisplayOrder
self.nameColorsChannelMinRequiredBoostLevel = nameColorsChannelMinRequiredBoostLevel self.nameColorsChannelMinRequiredBoostLevel = nameColorsChannelMinRequiredBoostLevel
self.profileColorsChannelMinRequiredBoostLevel = profileColorsChannelMinRequiredBoostLevel
self.profileColorsGroupMinRequiredBoostLevel = profileColorsGroupMinRequiredBoostLevel self.profileColorsGroupMinRequiredBoostLevel = profileColorsGroupMinRequiredBoostLevel
} }
@ -187,6 +191,7 @@ public class PeerNameColors: Equatable {
var profileDisplayOrder: [Int32] = [] var profileDisplayOrder: [Int32] = []
var nameColorsChannelMinRequiredBoostLevel: [Int32: Int32] = [:] var nameColorsChannelMinRequiredBoostLevel: [Int32: Int32] = [:]
var profileColorsChannelMinRequiredBoostLevel: [Int32: Int32] = [:]
var profileColorsGroupMinRequiredBoostLevel: [Int32: Int32] = [:] var profileColorsGroupMinRequiredBoostLevel: [Int32: Int32] = [:]
if !availableReplyColors.options.isEmpty { if !availableReplyColors.options.isEmpty {
@ -216,6 +221,9 @@ public class PeerNameColors: Equatable {
if !availableProfileColors.options.isEmpty { if !availableProfileColors.options.isEmpty {
for option in availableProfileColors.options { for option in availableProfileColors.options {
if let requiredChannelMinBoostLevel = option.value.requiredChannelMinBoostLevel {
profileColorsChannelMinRequiredBoostLevel[option.key] = requiredChannelMinBoostLevel
}
if let requiredGroupMinBoostLevel = option.value.requiredGroupMinBoostLevel { if let requiredGroupMinBoostLevel = option.value.requiredGroupMinBoostLevel {
profileColorsGroupMinRequiredBoostLevel[option.key] = requiredGroupMinBoostLevel profileColorsGroupMinRequiredBoostLevel[option.key] = requiredGroupMinBoostLevel
} }
@ -257,6 +265,7 @@ public class PeerNameColors: Equatable {
profileStoryDarkColors: profileStoryDarkColors, profileStoryDarkColors: profileStoryDarkColors,
profileDisplayOrder: profileDisplayOrder, profileDisplayOrder: profileDisplayOrder,
nameColorsChannelMinRequiredBoostLevel: nameColorsChannelMinRequiredBoostLevel, nameColorsChannelMinRequiredBoostLevel: nameColorsChannelMinRequiredBoostLevel,
profileColorsChannelMinRequiredBoostLevel: profileColorsChannelMinRequiredBoostLevel,
profileColorsGroupMinRequiredBoostLevel: profileColorsGroupMinRequiredBoostLevel profileColorsGroupMinRequiredBoostLevel: profileColorsGroupMinRequiredBoostLevel
) )
} }

View File

@ -398,6 +398,7 @@ private final class SheetContent: CombinedComponent {
let insets: UIEdgeInsets let insets: UIEdgeInsets
let peerId: EnginePeer.Id let peerId: EnginePeer.Id
let isGroup: Bool
let mode: PremiumBoostLevelsScreen.Mode let mode: PremiumBoostLevelsScreen.Mode
let status: ChannelBoostStatus? let status: ChannelBoostStatus?
let boostState: InternalBoostState.DisplayData? let boostState: InternalBoostState.DisplayData?
@ -414,6 +415,7 @@ private final class SheetContent: CombinedComponent {
strings: PresentationStrings, strings: PresentationStrings,
insets: UIEdgeInsets, insets: UIEdgeInsets,
peerId: EnginePeer.Id, peerId: EnginePeer.Id,
isGroup: Bool,
mode: PremiumBoostLevelsScreen.Mode, mode: PremiumBoostLevelsScreen.Mode,
status: ChannelBoostStatus?, status: ChannelBoostStatus?,
boostState: InternalBoostState.DisplayData?, boostState: InternalBoostState.DisplayData?,
@ -429,6 +431,7 @@ private final class SheetContent: CombinedComponent {
self.strings = strings self.strings = strings
self.insets = insets self.insets = insets
self.peerId = peerId self.peerId = peerId
self.isGroup = isGroup
self.mode = mode self.mode = mode
self.status = status self.status = status
self.boostState = boostState self.boostState = boostState
@ -453,6 +456,9 @@ private final class SheetContent: CombinedComponent {
if lhs.peerId != rhs.peerId { if lhs.peerId != rhs.peerId {
return false return false
} }
if lhs.isGroup != rhs.isGroup {
return false
}
if lhs.mode != rhs.mode { if lhs.mode != rhs.mode {
return false return false
} }
@ -547,10 +553,7 @@ private final class SheetContent: CombinedComponent {
let iconName = "Premium/Boost" let iconName = "Premium/Boost"
let peerName = state.peer?.compactDisplayTitle ?? "" let peerName = state.peer?.compactDisplayTitle ?? ""
var isGroup = false let isGroup = component.isGroup
if let peer = state.peer, case let .channel(channel) = peer, case .group = channel.info {
isGroup = true
}
let level: Int let level: Int
let boosts: Int let boosts: Int
@ -681,7 +684,7 @@ private final class SheetContent: CombinedComponent {
isCurrent = mode == .current isCurrent = mode == .current
} }
case .features: case .features:
textString = "By gaining **boosts**, your group reaches higher levels and unlocks more features." textString = strings.GroupBoost_AdditionalFeaturesText
} }
let defaultTitle = strings.ChannelBoost_Level("\(level)").string let defaultTitle = strings.ChannelBoost_Level("\(level)").string
@ -1062,7 +1065,7 @@ private final class SheetContent: CombinedComponent {
var profileColorsAtLevel: [(Int32, Int32)] = [] var profileColorsAtLevel: [(Int32, Int32)] = []
var profileColorsCountMap: [Int32: Int32] = [:] var profileColorsCountMap: [Int32: Int32] = [:]
for color in context.component.context.peerNameColors.profileDisplayOrder { for color in context.component.context.peerNameColors.profileDisplayOrder {
if let level = context.component.context.peerNameColors.profileColorsGroupMinRequiredBoostLevel[color] { if let level = isGroup ? context.component.context.peerNameColors.profileColorsGroupMinRequiredBoostLevel[color] : context.component.context.peerNameColors.profileColorsChannelMinRequiredBoostLevel[color] {
if let current = profileColorsCountMap[level] { if let current = profileColorsCountMap[level] {
profileColorsCountMap[level] = current + 1 profileColorsCountMap[level] = current + 1
} else { } else {
@ -1103,11 +1106,6 @@ private final class SheetContent: CombinedComponent {
perks.append(.audioTranscription) perks.append(.audioTranscription)
} }
// if level >= premiumConfiguration.minChannelProfileColorLevel {
// let delta = min(level - premiumConfiguration.minChannelProfileColorLevel + 1, 2)
// perks.append(.profileColor(8 * delta))
// }
var profileColorsCount: Int32 = 0 var profileColorsCount: Int32 = 0
for (colorLevel, count) in profileColorsAtLevel { for (colorLevel, count) in profileColorsAtLevel {
if level >= colorLevel { if level >= colorLevel {
@ -1301,56 +1299,63 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
let component = context.component let component = context.component
var isGroup = false var isGroup: Bool?
if let peer = state.peer, case let .channel(channel) = peer, case .group = channel.info { if let peer = state.peer {
isGroup = true if case let .channel(channel) = peer, case .group = channel.info {
isGroup = true
} else {
isGroup = false
}
} }
let scroll = scroll.update( if let isGroup {
component: ScrollComponent<Empty>( let scroll = scroll.update(
content: AnyComponent( component: ScrollComponent<Empty>(
SheetContent( content: AnyComponent(
context: component.context, SheetContent(
theme: component.theme, context: component.context,
strings: component.strings, theme: component.theme,
insets: .zero, strings: component.strings,
peerId: component.peerId, insets: .zero,
mode: component.mode, peerId: component.peerId,
status: component.status, isGroup: isGroup,
boostState: component.boostState, mode: component.mode,
boost: component.boost, status: component.status,
copyLink: component.copyLink, boostState: component.boostState,
dismiss: component.dismiss, boost: component.boost,
openStats: component.openStats, copyLink: component.copyLink,
openGift: component.openGift, dismiss: component.dismiss,
openPeer: component.openPeer openStats: component.openStats,
) openGift: component.openGift,
openPeer: component.openPeer
)
),
contentInsets: UIEdgeInsets(top: topInset, left: 0.0, bottom: 0.0, right: 0.0),
contentOffsetUpdated: { [weak state] topContentOffset, _ in
state?.topContentOffset = topContentOffset
Queue.mainQueue().justDispatch {
state?.updated(transition: .immediate)
}
},
contentOffsetWillCommit: { _ in }
), ),
contentInsets: UIEdgeInsets(top: topInset, left: 0.0, bottom: 34.0, right: 0.0), availableSize: context.availableSize,
contentOffsetUpdated: { [weak state] topContentOffset, _ in transition: context.transition
state?.topContentOffset = topContentOffset )
Queue.mainQueue().justDispatch {
state?.updated(transition: .immediate) let background = background.update(
} component: Rectangle(color: theme.overallDarkAppearance ? theme.list.blocksBackgroundColor : theme.list.plainBackgroundColor),
}, availableSize: scroll.size,
contentOffsetWillCommit: { _ in } transition: context.transition
), )
availableSize: context.availableSize, context.add(background
transition: context.transition .position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0))
) )
let background = background.update( context.add(scroll
component: Rectangle(color: theme.overallDarkAppearance ? theme.list.blocksBackgroundColor : theme.list.plainBackgroundColor), .position(CGPoint(x: context.availableSize.width / 2.0, y: scroll.size.height / 2.0))
availableSize: scroll.size, )
transition: context.transition }
)
context.add(background
.position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0))
)
context.add(scroll
.position(CGPoint(x: context.availableSize.width / 2.0, y: scroll.size.height / 2.0))
)
let topPanel = topPanel.update( let topPanel = topPanel.update(
component: BlurredBackgroundComponent( component: BlurredBackgroundComponent(
@ -1399,13 +1404,12 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
case .customWallpaper: case .customWallpaper:
titleString = strings.ChannelBoost_CustomWallpaper titleString = strings.ChannelBoost_CustomWallpaper
case .audioTranscription: case .audioTranscription:
//TODO:localize titleString = strings.GroupBoost_AudioTranscription
titleString = "Audio Transcription"
case .emojiPack: case .emojiPack:
titleString = "Set Group Emoji Pack" titleString = strings.GroupBoost_EmojiPack
} }
} else { } else {
titleString = isGroup ? strings.GroupBoost_Title_Current : strings.ChannelBoost_Title_Current titleString = isGroup == true ? strings.GroupBoost_Title_Current : strings.ChannelBoost_Title_Current
} }
} else { } else {
titleString = strings.ChannelBoost_MaxLevelReached titleString = strings.ChannelBoost_MaxLevelReached
@ -1418,16 +1422,15 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
if let _ = remaining { if let _ = remaining {
if case .current = mode { if case .current = mode {
titleString = isGroup ? strings.GroupBoost_Title_Current : strings.ChannelBoost_Title_Current titleString = isGroup == true ? strings.GroupBoost_Title_Current : strings.ChannelBoost_Title_Current
} else { } else {
titleString = isGroup ? strings.GroupBoost_Title_Other : strings.ChannelBoost_Title_Other titleString = isGroup == true ? strings.GroupBoost_Title_Other : strings.ChannelBoost_Title_Other
} }
} else { } else {
titleString = strings.ChannelBoost_MaxLevelReached titleString = strings.ChannelBoost_MaxLevelReached
} }
case .features: case .features:
//TODO:localize titleString = strings.GroupBoost_AdditionalFeatures
titleString = "Additional Features"
titleFont = Font.semibold(20.0) titleFont = Font.semibold(20.0)
} }
@ -1523,7 +1526,7 @@ private final class BoostLevelsContainerComponent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width - closeButton.size.width, y: 28.0)) .position(CGPoint(x: context.availableSize.width - closeButton.size.width, y: 28.0))
) )
return scroll.size return context.availableSize
} }
} }
} }