Various fixes

This commit is contained in:
Ilya Laktyushin 2024-02-28 23:17:35 +04:00
parent 936dceab02
commit ce3a6c3202
4 changed files with 161 additions and 39 deletions

View File

@ -1531,8 +1531,9 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
ApplicationSpecificNotice.dismissedPremiumColorsBadge(accountManager: context.sharedContext.accountManager), ApplicationSpecificNotice.dismissedPremiumColorsBadge(accountManager: context.sharedContext.accountManager),
ApplicationSpecificNotice.dismissedMessageTagsBadge(accountManager: context.sharedContext.accountManager), ApplicationSpecificNotice.dismissedMessageTagsBadge(accountManager: context.sharedContext.accountManager),
ApplicationSpecificNotice.dismissedLastSeenBadge(accountManager: context.sharedContext.accountManager), ApplicationSpecificNotice.dismissedLastSeenBadge(accountManager: context.sharedContext.accountManager),
ApplicationSpecificNotice.dismissedMessagePrivacyBadge(accountManager: context.sharedContext.accountManager) ApplicationSpecificNotice.dismissedMessagePrivacyBadge(accountManager: context.sharedContext.accountManager),
).startStrict(next: { [weak self] dismissedPremiumAppIconsBadge, dismissedPremiumWallpapersBadge, dismissedPremiumColorsBadge, dismissedMessageTagsBadge, dismissedLastSeenBadge, dismissedMessagePrivacyBadge in ApplicationSpecificNotice.dismissedBusinessBadge(accountManager: context.sharedContext.accountManager)
).startStrict(next: { [weak self] dismissedPremiumAppIconsBadge, dismissedPremiumWallpapersBadge, dismissedPremiumColorsBadge, dismissedMessageTagsBadge, dismissedLastSeenBadge, dismissedMessagePrivacyBadge, dismissedBusinessBadge in
guard let self else { guard let self else {
return return
} }
@ -1552,8 +1553,9 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
if !dismissedMessagePrivacyBadge { if !dismissedMessagePrivacyBadge {
newPerks.append(PremiumPerk.messagePrivacy.identifier) newPerks.append(PremiumPerk.messagePrivacy.identifier)
} }
//TODO: if !dismissedBusinessBadge {
newPerks.append(PremiumPerk.business.identifier) newPerks.append(PremiumPerk.business.identifier)
}
self.newPerks = newPerks self.newPerks = newPerks
self.updated() self.updated()
}) })
@ -1937,17 +1939,31 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
if case .business = context.component.mode, case .business = perk { if case .business = context.component.mode, case .business = perk {
continue continue
} }
let isNew = state.newPerks.contains(perk.identifier)
let titleComponent = AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: perk.title(strings: strings),
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 0
))
let titleCombinedComponent: AnyComponent<Empty>
if isNew {
titleCombinedComponent = AnyComponent(HStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: titleComponent),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(BadgeComponent(color: gradientColors[i], text: strings.Premium_New)))
], spacing: 5.0))
} else {
titleCombinedComponent = AnyComponent(HStack([AnyComponentWithIdentity(id: AnyHashable(0), component: titleComponent)], spacing: 0.0))
}
perksItems.append(AnyComponentWithIdentity(id: perksItems.count, component: AnyComponent(ListActionItemComponent( perksItems.append(AnyComponentWithIdentity(id: perksItems.count, component: AnyComponent(ListActionItemComponent(
theme: environment.theme, theme: environment.theme,
title: AnyComponent(VStack([ title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( AnyComponentWithIdentity(id: AnyHashable(0), component: titleCombinedComponent),
text: .plain(NSAttributedString(
string: perk.title(strings: strings),
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 0
))),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent( AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString( text: .plain(NSAttributedString(
string: perk.subtitle(strings: strings), string: perk.subtitle(strings: strings),
@ -2013,6 +2029,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let _ = ApplicationSpecificNotice.setDismissedMessagePrivacyBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone() let _ = ApplicationSpecificNotice.setDismissedMessagePrivacyBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
case .business: case .business:
demoSubject = .business demoSubject = .business
let _ = ApplicationSpecificNotice.setDismissedBusinessBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
default: default:
demoSubject = .doubleLimits demoSubject = .doubleLimits
} }
@ -3721,3 +3738,61 @@ private final class EmojiActionIconComponent: Component {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
} }
} }
private final class BadgeComponent: CombinedComponent {
let color: UIColor
let text: String
init(
color: UIColor,
text: String
) {
self.color = color
self.text = text
}
static func ==(lhs: BadgeComponent, rhs: BadgeComponent) -> Bool {
if lhs.color != rhs.color {
return false
}
if lhs.text != rhs.text {
return false
}
return true
}
static var body: Body {
let badgeBackground = Child(RoundedRectangle.self)
let badgeText = Child(MultilineTextComponent.self)
return { context in
let component = context.component
let badgeText = badgeText.update(
component: MultilineTextComponent(text: .plain(NSAttributedString(string: component.text, font: Font.semibold(11.0), textColor: .white))),
availableSize: context.availableSize,
transition: context.transition
)
let badgeSize = CGSize(width: badgeText.size.width + 7.0, height: 16.0)
let badgeBackground = badgeBackground.update(
component: RoundedRectangle(
color: component.color,
cornerRadius: 5.0
),
availableSize: badgeSize,
transition: context.transition
)
context.add(badgeBackground
.position(CGPoint(x: badgeSize.width / 2.0, y: badgeSize.height / 2.0))
)
context.add(badgeText
.position(CGPoint(x: badgeSize.width / 2.0, y: badgeSize.height / 2.0))
)
return badgeSize
}
}
}

View File

@ -384,7 +384,27 @@ public class PremiumLimitsListScreen: ViewController {
let theme = self.presentationData.theme let theme = self.presentationData.theme
let strings = self.presentationData.strings let strings = self.presentationData.strings
if let stickers = self.stickers, let appIcons = self.appIcons, let configuration = self.promoConfiguration { let videos: [String: TelegramMediaFile] = self.promoConfiguration?.videos ?? [:]
let stickers = self.stickers ?? []
let appIcons = self.appIcons ?? []
let isReady: Bool
switch controller.subject {
case .premiumStickers:
isReady = !stickers.isEmpty
case .appIcons:
isReady = !appIcons.isEmpty
case .stories:
isReady = true
case .doubleLimits:
isReady = true
case .business:
isReady = true
default:
isReady = !videos.isEmpty
}
if isReady {
let context = controller.context let context = controller.context
let textColor = theme.actionSheet.primaryTextColor let textColor = theme.actionSheet.primaryTextColor
@ -482,7 +502,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .bottom, position: .bottom,
videoFile: configuration.videos["more_upload"], videoFile: videos["more_upload"],
decoration: .dataRain decoration: .dataRain
)), )),
title: strings.Premium_UploadSize, title: strings.Premium_UploadSize,
@ -500,7 +520,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["faster_download"], videoFile: videos["faster_download"],
decoration: .fasterStars decoration: .fasterStars
)), )),
title: strings.Premium_FasterSpeed, title: strings.Premium_FasterSpeed,
@ -518,7 +538,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["voice_to_text"], videoFile: videos["voice_to_text"],
decoration: .badgeStars decoration: .badgeStars
)), )),
title: strings.Premium_VoiceToText, title: strings.Premium_VoiceToText,
@ -536,7 +556,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .bottom, position: .bottom,
videoFile: configuration.videos["no_ads"], videoFile: videos["no_ads"],
decoration: .swirlStars decoration: .swirlStars
)), )),
title: strings.Premium_NoAds, title: strings.Premium_NoAds,
@ -554,7 +574,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["infinite_reactions"], videoFile: videos["infinite_reactions"],
decoration: .swirlStars decoration: .swirlStars
)), )),
title: strings.Premium_InfiniteReactions, title: strings.Premium_InfiniteReactions,
@ -593,7 +613,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["emoji_status"], videoFile: videos["emoji_status"],
decoration: .badgeStars decoration: .badgeStars
)), )),
title: strings.Premium_EmojiStatus, title: strings.Premium_EmojiStatus,
@ -611,7 +631,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["advanced_chat_management"], videoFile: videos["advanced_chat_management"],
decoration: .swirlStars decoration: .swirlStars
)), )),
title: strings.Premium_ChatManagement, title: strings.Premium_ChatManagement,
@ -629,7 +649,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["profile_badge"], videoFile: videos["profile_badge"],
decoration: .badgeStars decoration: .badgeStars
)), )),
title: strings.Premium_Badge, title: strings.Premium_Badge,
@ -647,7 +667,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["animated_userpics"], videoFile: videos["animated_userpics"],
decoration: .swirlStars decoration: .swirlStars
)), )),
title: strings.Premium_Avatar, title: strings.Premium_Avatar,
@ -681,7 +701,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .bottom, position: .bottom,
videoFile: configuration.videos["animated_emoji"], videoFile: videos["animated_emoji"],
decoration: .emoji decoration: .emoji
)), )),
title: strings.Premium_AnimatedEmoji, title: strings.Premium_AnimatedEmoji,
@ -700,7 +720,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["translations"], videoFile: videos["translations"],
decoration: .hello decoration: .hello
)), )),
title: strings.Premium_Translation, title: strings.Premium_Translation,
@ -718,7 +738,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent( content: AnyComponent(PhoneDemoComponent(
context: context, context: context,
position: .top, position: .top,
videoFile: configuration.videos["peer_colors"], videoFile: videos["peer_colors"],
decoration: .badgeStars decoration: .badgeStars
)), )),
title: strings.Premium_Colors, title: strings.Premium_Colors,
@ -737,7 +757,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["wallpapers"], videoFile: videos["wallpapers"],
decoration: .swirlStars decoration: .swirlStars
)), )),
title: strings.Premium_Wallpapers, title: strings.Premium_Wallpapers,
@ -756,7 +776,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["saved_tags"], videoFile: videos["saved_tags"],
decoration: .tag decoration: .tag
)), )),
title: strings.Premium_MessageTags, title: strings.Premium_MessageTags,
@ -775,7 +795,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["last_seen"], videoFile: videos["last_seen"],
decoration: .badgeStars decoration: .badgeStars
)), )),
title: strings.Premium_LastSeen, title: strings.Premium_LastSeen,
@ -794,7 +814,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["message_privacy"], videoFile: videos["message_privacy"],
decoration: .swirlStars decoration: .swirlStars
)), )),
title: strings.Premium_MessagePrivacy, title: strings.Premium_MessagePrivacy,
@ -846,7 +866,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["business_location"], videoFile: videos["business_location"],
decoration: .business decoration: .business
)), )),
title: strings.Business_Location, title: strings.Business_Location,
@ -866,7 +886,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["business_hours"], videoFile: videos["business_hours"],
decoration: .business decoration: .business
)), )),
title: strings.Business_OpeningHours, title: strings.Business_OpeningHours,
@ -886,7 +906,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["quick_replies"], videoFile: videos["quick_replies"],
decoration: .business decoration: .business
)), )),
title: strings.Business_QuickReplies, title: strings.Business_QuickReplies,
@ -906,7 +926,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["greeting_message"], videoFile: videos["greeting_message"],
decoration: .business decoration: .business
)), )),
title: strings.Business_GreetingMessages, title: strings.Business_GreetingMessages,
@ -926,7 +946,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["away_message"], videoFile: videos["away_message"],
decoration: .business decoration: .business
)), )),
title: strings.Business_AwayMessages, title: strings.Business_AwayMessages,
@ -946,7 +966,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context, context: context,
position: .top, position: .top,
model: .island, model: .island,
videoFile: configuration.videos["business_bots"], videoFile: videos["business_bots"],
decoration: .business decoration: .business
)), )),
title: strings.Business_Chatbots, title: strings.Business_Chatbots,

View File

@ -199,6 +199,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
case savedMessageTagLabelSuggestion = 65 case savedMessageTagLabelSuggestion = 65
case dismissedLastSeenBadge = 66 case dismissedLastSeenBadge = 66
case dismissedMessagePrivacyBadge = 67 case dismissedMessagePrivacyBadge = 67
case dismissedBusinessBadge = 68
var key: ValueBoxKey { var key: ValueBoxKey {
let v = ValueBoxKey(length: 4) let v = ValueBoxKey(length: 4)
@ -529,6 +530,10 @@ private struct ApplicationSpecificNoticeKeys {
static func dismissedMessagePrivacyBadge() -> NoticeEntryKey { static func dismissedMessagePrivacyBadge() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedMessagePrivacyBadge.key) return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedMessagePrivacyBadge.key)
} }
static func dismissedBusinessBadge() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedBusinessBadge.key)
}
} }
public struct ApplicationSpecificNotice { public struct ApplicationSpecificNotice {
@ -2223,4 +2228,25 @@ public struct ApplicationSpecificNotice {
} }
|> take(1) |> take(1)
} }
public static func setDismissedBusinessBadge(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Never, NoError> {
return accountManager.transaction { transaction -> Void in
if let entry = CodableEntry(ApplicationSpecificBoolNotice()) {
transaction.setNotice(ApplicationSpecificNoticeKeys.dismissedBusinessBadge(), entry)
}
}
|> ignoreValues
}
public static func dismissedBusinessBadge(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Bool, NoError> {
return accountManager.noticeEntry(key: ApplicationSpecificNoticeKeys.dismissedBusinessBadge())
|> map { view -> Bool in
if let _ = view.value?.get(ApplicationSpecificBoolNotice.self) {
return true
} else {
return false
}
}
|> take(1)
}
} }

View File

@ -345,16 +345,17 @@ public final class AvatarStoryIndicatorComponent: Component {
} }
let colorSpace = CGColorSpaceCreateDeviceRGB() let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! if let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations) {
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) }
} }
} }
} 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 { 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) let path = 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.27))
context.addPath(path.cgPath)
} else { } 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))
} }