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.dismissedMessageTagsBadge(accountManager: context.sharedContext.accountManager),
ApplicationSpecificNotice.dismissedLastSeenBadge(accountManager: context.sharedContext.accountManager),
ApplicationSpecificNotice.dismissedMessagePrivacyBadge(accountManager: context.sharedContext.accountManager)
).startStrict(next: { [weak self] dismissedPremiumAppIconsBadge, dismissedPremiumWallpapersBadge, dismissedPremiumColorsBadge, dismissedMessageTagsBadge, dismissedLastSeenBadge, dismissedMessagePrivacyBadge in
ApplicationSpecificNotice.dismissedMessagePrivacyBadge(accountManager: context.sharedContext.accountManager),
ApplicationSpecificNotice.dismissedBusinessBadge(accountManager: context.sharedContext.accountManager)
).startStrict(next: { [weak self] dismissedPremiumAppIconsBadge, dismissedPremiumWallpapersBadge, dismissedPremiumColorsBadge, dismissedMessageTagsBadge, dismissedLastSeenBadge, dismissedMessagePrivacyBadge, dismissedBusinessBadge in
guard let self else {
return
}
@ -1552,8 +1553,9 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
if !dismissedMessagePrivacyBadge {
newPerks.append(PremiumPerk.messagePrivacy.identifier)
}
//TODO:
newPerks.append(PremiumPerk.business.identifier)
if !dismissedBusinessBadge {
newPerks.append(PremiumPerk.business.identifier)
}
self.newPerks = newPerks
self.updated()
})
@ -1937,17 +1939,31 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
if case .business = context.component.mode, case .business = perk {
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(
theme: environment.theme,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: perk.title(strings: strings),
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 0
))),
AnyComponentWithIdentity(id: AnyHashable(0), component: titleCombinedComponent),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: perk.subtitle(strings: strings),
@ -2013,6 +2029,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
let _ = ApplicationSpecificNotice.setDismissedMessagePrivacyBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
case .business:
demoSubject = .business
let _ = ApplicationSpecificNotice.setDismissedBusinessBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
default:
demoSubject = .doubleLimits
}
@ -3721,3 +3738,61 @@ private final class EmojiActionIconComponent: Component {
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 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 textColor = theme.actionSheet.primaryTextColor
@ -482,7 +502,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .bottom,
videoFile: configuration.videos["more_upload"],
videoFile: videos["more_upload"],
decoration: .dataRain
)),
title: strings.Premium_UploadSize,
@ -500,7 +520,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["faster_download"],
videoFile: videos["faster_download"],
decoration: .fasterStars
)),
title: strings.Premium_FasterSpeed,
@ -518,7 +538,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["voice_to_text"],
videoFile: videos["voice_to_text"],
decoration: .badgeStars
)),
title: strings.Premium_VoiceToText,
@ -536,7 +556,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .bottom,
videoFile: configuration.videos["no_ads"],
videoFile: videos["no_ads"],
decoration: .swirlStars
)),
title: strings.Premium_NoAds,
@ -554,7 +574,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["infinite_reactions"],
videoFile: videos["infinite_reactions"],
decoration: .swirlStars
)),
title: strings.Premium_InfiniteReactions,
@ -593,7 +613,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["emoji_status"],
videoFile: videos["emoji_status"],
decoration: .badgeStars
)),
title: strings.Premium_EmojiStatus,
@ -611,7 +631,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["advanced_chat_management"],
videoFile: videos["advanced_chat_management"],
decoration: .swirlStars
)),
title: strings.Premium_ChatManagement,
@ -629,7 +649,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["profile_badge"],
videoFile: videos["profile_badge"],
decoration: .badgeStars
)),
title: strings.Premium_Badge,
@ -647,7 +667,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["animated_userpics"],
videoFile: videos["animated_userpics"],
decoration: .swirlStars
)),
title: strings.Premium_Avatar,
@ -681,7 +701,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .bottom,
videoFile: configuration.videos["animated_emoji"],
videoFile: videos["animated_emoji"],
decoration: .emoji
)),
title: strings.Premium_AnimatedEmoji,
@ -700,7 +720,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["translations"],
videoFile: videos["translations"],
decoration: .hello
)),
title: strings.Premium_Translation,
@ -718,7 +738,7 @@ public class PremiumLimitsListScreen: ViewController {
content: AnyComponent(PhoneDemoComponent(
context: context,
position: .top,
videoFile: configuration.videos["peer_colors"],
videoFile: videos["peer_colors"],
decoration: .badgeStars
)),
title: strings.Premium_Colors,
@ -737,7 +757,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["wallpapers"],
videoFile: videos["wallpapers"],
decoration: .swirlStars
)),
title: strings.Premium_Wallpapers,
@ -756,7 +776,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["saved_tags"],
videoFile: videos["saved_tags"],
decoration: .tag
)),
title: strings.Premium_MessageTags,
@ -775,7 +795,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["last_seen"],
videoFile: videos["last_seen"],
decoration: .badgeStars
)),
title: strings.Premium_LastSeen,
@ -794,7 +814,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["message_privacy"],
videoFile: videos["message_privacy"],
decoration: .swirlStars
)),
title: strings.Premium_MessagePrivacy,
@ -846,7 +866,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["business_location"],
videoFile: videos["business_location"],
decoration: .business
)),
title: strings.Business_Location,
@ -866,7 +886,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["business_hours"],
videoFile: videos["business_hours"],
decoration: .business
)),
title: strings.Business_OpeningHours,
@ -886,7 +906,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["quick_replies"],
videoFile: videos["quick_replies"],
decoration: .business
)),
title: strings.Business_QuickReplies,
@ -906,7 +926,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["greeting_message"],
videoFile: videos["greeting_message"],
decoration: .business
)),
title: strings.Business_GreetingMessages,
@ -926,7 +946,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["away_message"],
videoFile: videos["away_message"],
decoration: .business
)),
title: strings.Business_AwayMessages,
@ -946,7 +966,7 @@ public class PremiumLimitsListScreen: ViewController {
context: context,
position: .top,
model: .island,
videoFile: configuration.videos["business_bots"],
videoFile: videos["business_bots"],
decoration: .business
)),
title: strings.Business_Chatbots,

View File

@ -199,6 +199,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
case savedMessageTagLabelSuggestion = 65
case dismissedLastSeenBadge = 66
case dismissedMessagePrivacyBadge = 67
case dismissedBusinessBadge = 68
var key: ValueBoxKey {
let v = ValueBoxKey(length: 4)
@ -529,6 +530,10 @@ private struct ApplicationSpecificNoticeKeys {
static func dismissedMessagePrivacyBadge() -> NoticeEntryKey {
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 {
@ -2223,4 +2228,25 @@ public struct ApplicationSpecificNotice {
}
|> 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 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())
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())
}
}
}
} else {
let lineWidth: CGFloat = component.hasUnseen ? component.activeLineWidth : component.inactiveLineWidth
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)
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 {
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))
}