Various improvements

This commit is contained in:
Ilya Laktyushin
2024-03-28 21:46:01 +04:00
parent 8465b93839
commit a7caa2fab9
7 changed files with 69 additions and 22 deletions

View File

@@ -3,4 +3,5 @@ import Foundation
public struct GlobalExperimentalSettings { public struct GlobalExperimentalSettings {
public static var isAppStoreBuild: Bool = false public static var isAppStoreBuild: Bool = false
public static var enableFeed: Bool = false public static var enableFeed: Bool = false
public static var enableWIPStickers: Bool = false
} }

View File

@@ -991,7 +991,13 @@ private enum StatsEntry: ItemListNodeEntry {
switch transaction { switch transaction {
case let .proceeds(_, fromDate, toDate): case let .proceeds(_, fromDate, toDate):
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Proceeds, font: font, textColor: theme.list.itemPrimaryTextColor) title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Proceeds, font: font, textColor: theme.list.itemPrimaryTextColor)
detailText = "\(stringForMediumCompactDate(timestamp: fromDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)) \(stringForMediumCompactDate(timestamp: toDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat))" let fromDateString = stringForMediumCompactDate(timestamp: fromDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false)
let toDateString = stringForMediumCompactDate(timestamp: toDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false)
if fromDateString == toDateString {
detailText = stringForMediumCompactDate(timestamp: toDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: true)
} else {
detailText = "\(fromDateString) \(toDateString)"
}
case let .withdrawal(status, _, date, provider, _, _): case let .withdrawal(status, _, date, provider, _, _):
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Withdrawal(provider).string, font: font, textColor: theme.list.itemPrimaryTextColor) title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Withdrawal(provider).string, font: font, textColor: theme.list.itemPrimaryTextColor)
labelColor = theme.list.itemDestructiveColor labelColor = theme.list.itemDestructiveColor
@@ -999,7 +1005,7 @@ private enum StatsEntry: ItemListNodeEntry {
case .succeed: case .succeed:
detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat) detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
case .failed: case .failed:
detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat) + " \(presentationData.strings.Monetization_Transaction_Failed)" detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false) + " \(presentationData.strings.Monetization_Transaction_Failed)"
detailColor = .destructive detailColor = .destructive
case .pending: case .pending:
detailText = presentationData.strings.Monetization_Transaction_Pending detailText = presentationData.strings.Monetization_Transaction_Pending

View File

@@ -73,6 +73,8 @@ private final class SheetContent: CombinedComponent {
let infoTitle = Child(MultilineTextWithEntitiesComponent.self) let infoTitle = Child(MultilineTextWithEntitiesComponent.self)
let infoText = Child(MultilineTextComponent.self) let infoText = Child(MultilineTextComponent.self)
let spaceRegex = try? NSRegularExpression(pattern: "\\[(.*?)\\]", options: [])
return { context in return { context in
let environment = context.environment[EnvironmentType.self] let environment = context.environment[EnvironmentType.self]
let component = context.component let component = context.component
@@ -146,8 +148,7 @@ private final class SheetContent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + title.size.height / 2.0)) .position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + title.size.height / 2.0))
) )
contentSize.height += title.size.height contentSize.height += title.size.height
contentSize.height += spacing contentSize.height += spacing - 2.0
var items: [AnyComponentWithIdentity<Empty>] = [] var items: [AnyComponentWithIdentity<Empty>] = []
items.append( items.append(
@@ -199,7 +200,7 @@ private final class SheetContent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + list.size.height / 2.0)) .position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + list.size.height / 2.0))
) )
contentSize.height += list.size.height contentSize.height += list.size.height
contentSize.height += spacing - 9.0 contentSize.height += spacing - 13.0
let infoTitleString = strings.Monetization_Intro_Info_Title let infoTitleString = strings.Monetization_Intro_Info_Title
let infoTitleAttributedString = NSMutableAttributedString(string: infoTitleString, font: titleFont, textColor: textColor) let infoTitleAttributedString = NSMutableAttributedString(string: infoTitleString, font: titleFont, textColor: textColor)
@@ -225,7 +226,21 @@ private final class SheetContent: CombinedComponent {
} }
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
let infoString = strings.Monetization_Intro_Info_Text var infoString = strings.Monetization_Intro_Info_Text
if let spaceRegex {
let nsRange = NSRange(infoString.startIndex..., in: infoString)
let matches = spaceRegex.matches(in: infoString, options: [], range: nsRange)
var modifiedString = infoString
for match in matches.reversed() {
let matchRange = Range(match.range, in: infoString)!
let matchedSubstring = String(infoString[matchRange])
let replacedSubstring = matchedSubstring.replacingOccurrences(of: " ", with: "\u{00A0}")
modifiedString.replaceSubrange(matchRange, with: replacedSubstring)
}
infoString = modifiedString
}
let infoAttributedString = parseMarkdownIntoAttributedString(infoString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString let infoAttributedString = parseMarkdownIntoAttributedString(infoString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
if let range = infoAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 { if let range = infoAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 {
infoAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: infoAttributedString.string)) infoAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: infoAttributedString.string))
@@ -583,7 +598,7 @@ private final class ParagraphComponent: CombinedComponent {
.position(CGPoint(x: 47.0, y: textTopInset + 18.0)) .position(CGPoint(x: 47.0, y: textTopInset + 18.0))
) )
return CGSize(width: context.availableSize.width, height: textTopInset + title.size.height + text.size.height + 20.0) return CGSize(width: context.availableSize.width, height: textTopInset + title.size.height + text.size.height + 18.0)
} }
} }
} }

View File

@@ -495,6 +495,9 @@ private final class StickerPackContainer: ASDisplayNode {
if let (info, _, _) = strongSelf.currentStickerPack, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if let (info, _, _) = strongSelf.currentStickerPack, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
canEdit = true canEdit = true
} }
if !GlobalExperimentalSettings.enableWIPStickers {
canEdit = false
}
let accountPeerId = strongSelf.context.account.peerId let accountPeerId = strongSelf.context.account.peerId
return combineLatest( return combineLatest(
@@ -973,7 +976,7 @@ private final class StickerPackContainer: ASDisplayNode {
case .none: case .none:
buttonColor = self.presentationData.theme.list.itemAccentColor buttonColor = self.presentationData.theme.list.itemAccentColor
case let .result(info, _, installed): case let .result(info, _, installed):
if info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if GlobalExperimentalSettings.enableWIPStickers && info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
buttonColor = installed ? self.presentationData.theme.list.itemAccentColor : self.presentationData.theme.list.itemCheckColors.foregroundColor buttonColor = installed ? self.presentationData.theme.list.itemAccentColor : self.presentationData.theme.list.itemCheckColors.foregroundColor
} else { } else {
buttonColor = installed ? self.presentationData.theme.list.itemDestructiveColor : self.presentationData.theme.list.itemCheckColors.foregroundColor buttonColor = installed ? self.presentationData.theme.list.itemDestructiveColor : self.presentationData.theme.list.itemCheckColors.foregroundColor
@@ -1012,6 +1015,9 @@ private final class StickerPackContainer: ASDisplayNode {
if let info = self.currentStickerPack?.0, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if let info = self.currentStickerPack?.0, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
isEditable = true isEditable = true
} }
if !GlobalExperimentalSettings.enableWIPStickers {
isEditable = false
}
let transaction: StickerPackPreviewGridTransaction let transaction: StickerPackPreviewGridTransaction
if reload { if reload {
@@ -1100,7 +1106,7 @@ private final class StickerPackContainer: ASDisplayNode {
} }
}))) })))
if let (info, packItems, _) = self.currentStickerPack, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if GlobalExperimentalSettings.enableWIPStickers, let (info, packItems, _) = self.currentStickerPack, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
//TODO:localize //TODO:localize
items.append(.separator) items.append(.separator)
if packItems.count > 0 { if packItems.count > 0 {
@@ -1434,7 +1440,7 @@ private final class StickerPackContainer: ASDisplayNode {
} }
self.requestDismiss() self.requestDismiss()
} else if let (info, _, installed) = self.currentStickerPack { } else if let (info, _, installed) = self.currentStickerPack {
if installed, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if GlobalExperimentalSettings.enableWIPStickers, installed, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
self.updateIsEditing(!self.isEditing) self.updateIsEditing(!self.isEditing)
return return
} }
@@ -1509,7 +1515,7 @@ private final class StickerPackContainer: ASDisplayNode {
if let currentContents = self.currentContents, currentContents.count == 1, let content = currentContents.first, case let .result(info, _, installed) = content { if let currentContents = self.currentContents, currentContents.count == 1, let content = currentContents.first, case let .result(info, _, installed) = content {
if installed { if installed {
let text: String let text: String
if info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if GlobalExperimentalSettings.enableWIPStickers, info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
if self.isEditing { if self.isEditing {
var updated = false var updated = false
if let current = self.buttonNode.attributedTitle(for: .normal)?.string, !current.isEmpty && current != self.presentationData.strings.Common_Done { if let current = self.buttonNode.attributedTitle(for: .normal)?.string, !current.isEmpty && current != self.presentationData.strings.Common_Done {
@@ -1688,7 +1694,7 @@ private final class StickerPackContainer: ASDisplayNode {
self.controller?.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.StickerPack_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) self.controller?.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.StickerPack_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
self.controller?.dismiss(animated: true, completion: nil) self.controller?.dismiss(animated: true, completion: nil)
case let .result(info, items, installed): case let .result(info, items, installed):
isEditable = info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) isEditable = GlobalExperimentalSettings.enableWIPStickers && info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji)
self.onReady() self.onReady()
if !items.isEmpty && self.currentStickerPack == nil { if !items.isEmpty && self.currentStickerPack == nil {
if let _ = self.validLayout, abs(self.expandScrollProgress - 1.0) < .ulpOfOne { if let _ = self.validLayout, abs(self.expandScrollProgress - 1.0) < .ulpOfOne {
@@ -1772,7 +1778,7 @@ private final class StickerPackContainer: ASDisplayNode {
self.updateButton(count: count) self.updateButton(count: count)
} }
if info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if GlobalExperimentalSettings.enableWIPStickers && info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) {
entries.append(.add) entries.append(.add)
} }
} }
@@ -1873,7 +1879,7 @@ private final class StickerPackContainer: ASDisplayNode {
self.currentEntries = entries self.currentEntries = entries
if let controller = self.controller { if let controller = self.controller {
let transaction = StickerPackPreviewGridTransaction(previousList: previousEntries, list: entries, context: self.context, interaction: self.interaction, theme: self.presentationData.theme, strings: self.presentationData.strings, animationCache: controller.animationCache, animationRenderer: controller.animationRenderer, scrollToItem: nil, isEditable: info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji), isEditing: self.isEditing, invert: invert) let transaction = StickerPackPreviewGridTransaction(previousList: previousEntries, list: entries, context: self.context, interaction: self.interaction, theme: self.presentationData.theme, strings: self.presentationData.strings, animationCache: controller.animationCache, animationRenderer: controller.animationRenderer, scrollToItem: nil, isEditable: GlobalExperimentalSettings.enableWIPStickers && info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji), isEditing: self.isEditing, invert: invert)
self.enqueueTransaction(transaction) self.enqueueTransaction(transaction)
} }
} }
@@ -1933,7 +1939,7 @@ private final class StickerPackContainer: ASDisplayNode {
actionAreaBottomInset = 2.0 actionAreaBottomInset = 2.0
} }
} }
if let (info, _, isInstalled) = self.currentStickerPack, isInstalled, !info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji) { if let (info, _, isInstalled) = self.currentStickerPack, isInstalled, GlobalExperimentalSettings.enableWIPStickers && (!info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji)) {
buttonHeight = 42.0 buttonHeight = 42.0
actionAreaTopInset = 1.0 actionAreaTopInset = 1.0
actionAreaBottomInset = 2.0 actionAreaBottomInset = 2.0

View File

@@ -58,7 +58,7 @@ public func getDateTimeComponents(timestamp: Int32) -> (day: Int32, month: Int32
return (timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year, timeinfo.tm_hour, timeinfo.tm_min) return (timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year, timeinfo.tm_hour, timeinfo.tm_min)
} }
public func stringForMediumCompactDate(timestamp: Int32, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) -> String { public func stringForMediumCompactDate(timestamp: Int32, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, withTime: Bool = true) -> String {
var t: time_t = Int(timestamp) var t: time_t = Int(timestamp)
var timeinfo = tm() var timeinfo = tm()
localtime_r(&t, &timeinfo); localtime_r(&t, &timeinfo);
@@ -66,14 +66,18 @@ public func stringForMediumCompactDate(timestamp: Int32, strings: PresentationSt
let day = timeinfo.tm_mday let day = timeinfo.tm_mday
let month = monthAtIndex(Int(timeinfo.tm_mon), strings: strings) let month = monthAtIndex(Int(timeinfo.tm_mon), strings: strings)
let timeString = stringForShortTimestamp(hours: Int32(timeinfo.tm_hour), minutes: Int32(timeinfo.tm_min), dateTimeFormat: dateTimeFormat) let timeString: String
if withTime {
timeString = " \(stringForShortTimestamp(hours: Int32(timeinfo.tm_hour), minutes: Int32(timeinfo.tm_min), dateTimeFormat: dateTimeFormat))"
} else {
timeString = ""
}
let dateString: String let dateString: String
switch dateTimeFormat.dateFormat { switch dateTimeFormat.dateFormat {
case .monthFirst: case .monthFirst:
dateString = String(format: "%@ %02d %@", month, day, timeString) dateString = String(format: "%@ %02d%@", month, day, timeString)
case .dayFirst: case .dayFirst:
dateString = String(format: "%02d %@ %@", day, month, timeString) dateString = String(format: "%02d %@%@", day, month, timeString)
} }
return dateString return dateString
} }

View File

@@ -72,6 +72,8 @@ private final class ScrollContent: CombinedComponent {
let infoBackground = Child(RoundedRectangle.self) let infoBackground = Child(RoundedRectangle.self)
let infoTitle = Child(MultilineTextComponent.self) let infoTitle = Child(MultilineTextComponent.self)
let infoText = Child(MultilineTextComponent.self) let infoText = Child(MultilineTextComponent.self)
let spaceRegex = try? NSRegularExpression(pattern: "\\[(.*?)\\]", options: [])
return { context in return { context in
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
@@ -240,7 +242,20 @@ private final class ScrollContent: CombinedComponent {
state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: linkColor)!, theme) state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: linkColor)!, theme)
} }
let infoString = strings.AdsInfo_Launch_Text var infoString = strings.AdsInfo_Launch_Text
if let spaceRegex {
let nsRange = NSRange(infoString.startIndex..., in: infoString)
let matches = spaceRegex.matches(in: infoString, options: [], range: nsRange)
var modifiedString = infoString
for match in matches.reversed() {
let matchRange = Range(match.range, in: infoString)!
let matchedSubstring = String(infoString[matchRange])
let replacedSubstring = matchedSubstring.replacingOccurrences(of: " ", with: "\u{00A0}")
modifiedString.replaceSubrange(matchRange, with: replacedSubstring)
}
infoString = modifiedString
}
let infoAttributedString = parseMarkdownIntoAttributedString(infoString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString let infoAttributedString = parseMarkdownIntoAttributedString(infoString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
if let range = infoAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 { if let range = infoAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 {
infoAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: infoAttributedString.string)) infoAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: infoAttributedString.string))

View File

@@ -184,7 +184,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings
let stickerItems = EmojiPagerContentComponent.stickerInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer, stickerNamespaces: stickerNamespaces, stickerOrderedItemListCollectionIds: stickerOrderedItemListCollectionIds, chatPeerId: chatPeerId, hasSearch: hasSearch, hasTrending: hasTrending, forceHasPremium: false, hasEdit: true, hideBackground: hideBackground) let stickerItems = EmojiPagerContentComponent.stickerInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer, stickerNamespaces: stickerNamespaces, stickerOrderedItemListCollectionIds: stickerOrderedItemListCollectionIds, chatPeerId: chatPeerId, hasSearch: hasSearch, hasTrending: hasTrending, forceHasPremium: false, hasEdit: GlobalExperimentalSettings.enableWIPStickers, hideBackground: hideBackground)
let reactions: Signal<[String], NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()) let reactions: Signal<[String], NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App())
|> map { appConfiguration -> [String] in |> map { appConfiguration -> [String] in