mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge commit '0e58f827b6'
This commit is contained in:
commit
370bcdfe04
10 changed files with 113 additions and 74 deletions
|
|
@ -15697,8 +15697,8 @@ Error: %8$@";
|
|||
"Gift.Craft.Info.Paragraph3.Title" = "Affect the Result";
|
||||
"Gift.Craft.Info.Paragraph3.Text" = "Use gifts with the same attribute to boost it's chance.";
|
||||
"Gift.Craft.Info.Understood" = "Understood";
|
||||
"Gift.Craft.Unavailable.Title" = "Try Later";
|
||||
"Gift.Craft.Unavailable.Text" = "You will be able to craft this gift on %@.";
|
||||
"Gift.Craft.Unavailable.Title" = "Crafting Unavailable";
|
||||
"Gift.Craft.Unavailable.Text" = "This gift will become available for crafting on **%@**.";
|
||||
"Gift.Craft.Error.NotAvailable" = "One of the gifts is not available for crafting.";
|
||||
|
||||
"Gift.Craft.Select.Title" = "Select Gifts";
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@ public final class ResizableSheetComponent<ChildEnvironmentType: Sendable & Equa
|
|||
environment: {},
|
||||
containerSize: CGSize(width: containerSize.width - 66.0 * 2.0, height: 66.0)
|
||||
)
|
||||
let titleItemFrame = CGRect(origin: CGPoint(x: rawSideInset + floorToScreenPixels((containerSize.width - titleItemSize.width)) / 2.0, y: floorToScreenPixels(36.0 - titleItemSize.height * 0.5)), size: titleItemSize)
|
||||
let titleItemFrame = CGRect(origin: CGPoint(x: rawSideInset + floorToScreenPixels((containerSize.width - titleItemSize.width)) / 2.0, y: floorToScreenPixels(38.0 - titleItemSize.height * 0.5)), size: titleItemSize)
|
||||
if let view = titleItemView.view {
|
||||
if view.superview == nil {
|
||||
self.navigationBarContainer.addSubview(view)
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ swift_library(
|
|||
"//submodules/TelegramUI/Components/Calls/VideoChatMicButtonComponent",
|
||||
"//submodules/TelegramUI/Components/AlertComponent",
|
||||
"//submodules/TelegramUI/Components/AlertComponent/AlertInputFieldComponent",
|
||||
"//submodules/TelegramUI/Components/GlassControls",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import BalancedTextComponent
|
|||
import TelegramPresentationData
|
||||
import TelegramStringFormatting
|
||||
import Markdown
|
||||
import GlassControls
|
||||
|
||||
private final class ScheduleVideoChatSheetContentComponent: Component {
|
||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
|
@ -33,8 +34,8 @@ private final class ScheduleVideoChatSheetContentComponent: Component {
|
|||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let button = ComponentView<Empty>()
|
||||
private let cancelButton = ComponentView<Empty>()
|
||||
private let buttons = ComponentView<Empty>()
|
||||
private let actionButton = ComponentView<Empty>()
|
||||
|
||||
private let title = ComponentView<Empty>()
|
||||
private let mainText = ComponentView<Empty>()
|
||||
|
|
@ -110,6 +111,43 @@ private final class ScheduleVideoChatSheetContentComponent: Component {
|
|||
var contentHeight: CGFloat = 0.0
|
||||
contentHeight += 16.0
|
||||
|
||||
let buttonsSize = self.buttons.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(
|
||||
GlassControlPanelComponent(
|
||||
theme: environment.theme,
|
||||
leftItem: GlassControlPanelComponent.Item(
|
||||
items: [
|
||||
GlassControlGroupComponent.Item(
|
||||
id: AnyHashable("close"),
|
||||
content: .icon("Navigation/Close"),
|
||||
action: { [weak self] in
|
||||
guard let component = self?.component else {
|
||||
return
|
||||
}
|
||||
component.dismiss()
|
||||
}
|
||||
)
|
||||
],
|
||||
background: .panel
|
||||
),
|
||||
centralItem: nil,
|
||||
rightItem: nil,
|
||||
centerAlignmentIfPossible: true,
|
||||
isDark: true
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 16.0 * 2.0, height: 44.0)
|
||||
)
|
||||
if let buttonsView = self.buttons.view {
|
||||
if buttonsView.superview == nil {
|
||||
self.addSubview(buttonsView)
|
||||
}
|
||||
transition.setFrame(view: buttonsView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - buttonsSize.width) * 0.5), y: contentHeight), size: buttonsSize))
|
||||
}
|
||||
contentHeight += buttonsSize.height
|
||||
|
||||
let titleString = NSMutableAttributedString()
|
||||
titleString.append(NSAttributedString(string: environment.strings.VideoChat_ScheduleButtonTitle, font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor))
|
||||
|
||||
|
|
@ -126,9 +164,8 @@ private final class ScheduleVideoChatSheetContentComponent: Component {
|
|||
if titleView.superview == nil {
|
||||
self.addSubview(titleView)
|
||||
}
|
||||
transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: contentHeight), size: titleSize))
|
||||
transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: contentHeight - buttonsSize.height * 0.5 - titleSize.height * 0.5), size: titleSize))
|
||||
}
|
||||
contentHeight += titleSize.height
|
||||
contentHeight += 16.0
|
||||
|
||||
let pickerView: UIDatePicker
|
||||
|
|
@ -221,17 +258,20 @@ private final class ScheduleVideoChatSheetContentComponent: Component {
|
|||
transition.setFrame(view: mainTextView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - mainTextSize.width) * 0.5), y: contentHeight), size: mainTextSize))
|
||||
}
|
||||
contentHeight += mainTextSize.height
|
||||
contentHeight += 10.0
|
||||
contentHeight += 32.0
|
||||
|
||||
var buttonContents: [AnyComponentWithIdentity<Empty>] = []
|
||||
buttonContents.append(AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(
|
||||
Text(text: buttonTitle, font: Font.semibold(17.0), color: environment.theme.list.itemCheckColors.foregroundColor)
|
||||
)))
|
||||
let buttonTransition = transition
|
||||
let buttonSize = self.button.update(
|
||||
|
||||
let buttonInsets = ContainerViewLayout.concentricInsets(bottomInset: environment.safeInsets.bottom, innerDiameter: 52.0, sideInset: 30.0)
|
||||
let buttonSize = self.actionButton.update(
|
||||
transition: buttonTransition,
|
||||
component: AnyComponent(ButtonComponent(
|
||||
background: ButtonComponent.Background(
|
||||
style: .glass,
|
||||
color: UIColor(rgb: 0x3252EF),
|
||||
foreground: .white,
|
||||
pressedColor: UIColor(rgb: 0x3252EF).withMultipliedAlpha(0.8)
|
||||
|
|
@ -250,56 +290,17 @@ private final class ScheduleVideoChatSheetContentComponent: Component {
|
|||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0)
|
||||
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 52.0)
|
||||
)
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: buttonSize)
|
||||
if let buttonView = self.button.view {
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: buttonInsets.left, y: contentHeight), size: buttonSize)
|
||||
if let buttonView = self.actionButton.view {
|
||||
if buttonView.superview == nil {
|
||||
self.addSubview(buttonView)
|
||||
}
|
||||
transition.setFrame(view: buttonView, frame: buttonFrame)
|
||||
}
|
||||
contentHeight += buttonSize.height
|
||||
contentHeight += 10.0
|
||||
|
||||
let cancelButtonSize = self.cancelButton.update(
|
||||
transition: buttonTransition,
|
||||
component: AnyComponent(ButtonComponent(
|
||||
background: ButtonComponent.Background(
|
||||
color: UIColor(rgb: 0x2B2B2F),
|
||||
foreground: .white,
|
||||
pressedColor: UIColor(rgb: 0x2B2B2F).withMultipliedAlpha(0.8)
|
||||
),
|
||||
content: AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(
|
||||
Text(text: environment.strings.Common_Cancel, font: Font.semibold(17.0), color: environment.theme.list.itemPrimaryTextColor)
|
||||
)),
|
||||
isEnabled: true,
|
||||
tintWhenDisabled: false,
|
||||
displaysProgress: false,
|
||||
action: { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
component.dismiss()
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0)
|
||||
)
|
||||
let cancelButtonFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: cancelButtonSize)
|
||||
if let cancelButtonView = self.cancelButton.view {
|
||||
if cancelButtonView.superview == nil {
|
||||
self.addSubview(cancelButtonView)
|
||||
}
|
||||
transition.setFrame(view: cancelButtonView, frame: cancelButtonFrame)
|
||||
}
|
||||
contentHeight += cancelButtonSize.height
|
||||
|
||||
if environment.safeInsets.bottom.isZero {
|
||||
contentHeight += 16.0
|
||||
} else {
|
||||
contentHeight += environment.safeInsets.bottom + 14.0
|
||||
}
|
||||
contentHeight += buttonInsets.bottom
|
||||
|
||||
return CGSize(width: availableSize.width, height: contentHeight)
|
||||
}
|
||||
|
|
@ -407,7 +408,8 @@ private final class ScheduleVideoChatSheetScreenComponent: Component {
|
|||
})
|
||||
}
|
||||
)),
|
||||
backgroundColor: .color(UIColor(rgb: 0x1C1C1E)),
|
||||
style: .glass,
|
||||
backgroundColor: .color(UIColor(rgb: 0x1c1c1e)),
|
||||
animateOut: self.sheetAnimateOut
|
||||
)),
|
||||
environment: {
|
||||
|
|
|
|||
|
|
@ -1517,6 +1517,7 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||
let state = context.state
|
||||
|
||||
let strings = environment.strings
|
||||
let dateTimeFormat = environment.dateTimeFormat
|
||||
|
||||
if externalState.displayFailure {
|
||||
state.displayFailure = true
|
||||
|
|
@ -1846,6 +1847,9 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||
if let navigationController = controller()?.navigationController {
|
||||
var text: String = strings.Login_UnknownError
|
||||
switch error {
|
||||
case let .tooEarly(canCraftDate):
|
||||
let dateString = stringForFullDate(timestamp: canCraftDate, strings: strings, dateTimeFormat: dateTimeFormat)
|
||||
text = strings.Gift_Craft_Unavailable_Text(dateString).string
|
||||
case .unavailable:
|
||||
text = strings.Gift_Craft_Error_NotAvailable
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ final class SelectGiftPageContent: Component {
|
|||
private var craftStateDisposable: Disposable?
|
||||
|
||||
private var availableGifts: [GiftItem] = []
|
||||
private var giftMap: [Int64: GiftItem] = [:]
|
||||
private var giftMap: [Int64: ProfileGiftsContext.State.StarGift] = [:]
|
||||
|
||||
private var availableSize: CGSize?
|
||||
private var currentBounds: CGRect?
|
||||
|
|
@ -203,11 +203,27 @@ final class SelectGiftPageContent: Component {
|
|||
isEditing: false,
|
||||
mode: .grid,
|
||||
action: { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
guard let self, let component = self.component, let environment = self.environment else {
|
||||
return
|
||||
}
|
||||
HapticFeedback().impact(.light)
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if let profileGift = self.giftMap[gift.gift.id], let canCraftDate = profileGift.canCraftAt, currentTime < canCraftDate {
|
||||
let dateString = stringForFullDate(timestamp: canCraftDate, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
|
||||
let alertController = textAlertController(
|
||||
context: component.context,
|
||||
title: environment.strings.Gift_Craft_Unavailable_Title,
|
||||
text: environment.strings.Gift_Craft_Unavailable_Text(dateString).string,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: environment.strings.Common_OK, action: {})
|
||||
],
|
||||
parseMarkdown: true
|
||||
)
|
||||
environment.controller()?.present(alertController, in: .window(.root))
|
||||
return
|
||||
}
|
||||
|
||||
component.selectGift(gift)
|
||||
component.dismiss()
|
||||
},
|
||||
|
|
@ -322,7 +338,6 @@ final class SelectGiftPageContent: Component {
|
|||
self.availableGifts = [
|
||||
initialGiftItem
|
||||
]
|
||||
self.giftMap = [initialGiftItem.gift.id: initialGiftItem]
|
||||
|
||||
self.craftStateDisposable = (component.craftContext.state
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
|
|
@ -332,32 +347,28 @@ final class SelectGiftPageContent: Component {
|
|||
self.craftState = state
|
||||
|
||||
var items: [GiftItem] = []
|
||||
var map: [Int64: GiftItem] = [:]
|
||||
var foundInitial = false
|
||||
var giftMap: [Int64: ProfileGiftsContext.State.StarGift] = [:]
|
||||
var existingIds = Set<Int64>()
|
||||
for gift in state.gifts {
|
||||
guard let reference = gift.reference, case let .unique(uniqueGift) = gift.gift else {
|
||||
guard let reference = gift.reference, case let .unique(uniqueGift) = gift.gift, !existingIds.contains(uniqueGift.id) else {
|
||||
continue
|
||||
}
|
||||
existingIds.insert(uniqueGift.id)
|
||||
|
||||
let giftItem = GiftItem(
|
||||
gift: uniqueGift,
|
||||
reference: reference
|
||||
)
|
||||
map[uniqueGift.id] = giftItem
|
||||
if uniqueGift.id == component.gift.id {
|
||||
foundInitial = true
|
||||
} else {
|
||||
if component.selectedGiftIds.contains(uniqueGift.id) {
|
||||
continue
|
||||
}
|
||||
items.append(giftItem)
|
||||
giftMap[uniqueGift.id] = gift
|
||||
|
||||
if component.selectedGiftIds.contains(uniqueGift.id) {
|
||||
continue
|
||||
}
|
||||
items.append(giftItem)
|
||||
}
|
||||
|
||||
if !foundInitial {
|
||||
map[initialGiftItem.gift.id] = initialGiftItem
|
||||
}
|
||||
self.availableGifts = items
|
||||
self.giftMap = map
|
||||
self.giftMap = giftMap
|
||||
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1536,9 +1536,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||
controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(title: nil, text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
})))
|
||||
|
||||
if let _ = arguments.canCraftDate {
|
||||
var canCraft = false
|
||||
if let data = self.context.currentAppConfiguration.with({ $0 }).data {
|
||||
if let _ = data["ios_enable_crafting"] {
|
||||
canCraft = true
|
||||
} else if let isDev = data["dev"] as? Double, isDev == 1.0 {
|
||||
canCraft = true
|
||||
}
|
||||
}
|
||||
|
||||
if let _ = arguments.canCraftDate, canCraft {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_Craft, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Premium/Craft/Craft"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] c, _ in
|
||||
c?.dismiss(completion: nil)
|
||||
|
||||
|
|
|
|||
12
submodules/TelegramUI/Images.xcassets/Premium/Craft/Craft.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/Craft/Craft.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "craft.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
submodules/TelegramUI/Images.xcassets/Premium/Craft/Craft.imageset/craft.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/Craft/Craft.imageset/craft.pdf
vendored
Normal file
Binary file not shown.
|
|
@ -251,7 +251,7 @@ private final class SheetContent: CombinedComponent {
|
|||
return { context in
|
||||
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
|
||||
let state = context.state
|
||||
let theme = environment.theme
|
||||
let theme = environment.theme.withModalBlocksBackground()
|
||||
let strings = environment.strings
|
||||
|
||||
let topInset: CGFloat = environment.navigationHeight - 35.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue