mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge commit '63a37c5bec'
This commit is contained in:
commit
5aeb390d8c
13 changed files with 98 additions and 63 deletions
|
|
@ -15679,7 +15679,6 @@ Error: %8$@";
|
|||
"Gift.Craft.ViewVariants" = "View all craftable models";
|
||||
"Gift.Craft.BackdropTooltip" = "**%1$@%** chance the crafted gift will have **%2$@** backdrop.";
|
||||
"Gift.Craft.SymbolTooltip" = "**%1$@%** chance the crafted gift will have **%2$@** symbol.";
|
||||
"Gift.Craft.SuccessChanceSuffix" = "% Success Chance";
|
||||
"Gift.Craft.Craft" = "Craft %@";
|
||||
"Gift.Craft.Crafting.Title" = "Crafting";
|
||||
"Gift.Craft.Crafting.Description" = "If crafting fails, all used gifts\nwill be lost.";
|
||||
|
|
@ -15768,3 +15767,5 @@ Error: %8$@";
|
|||
"AppointAnotherOwner.Title" = "Choose New Owner";
|
||||
|
||||
"Gift.View.Context.Craft" = "Craft";
|
||||
|
||||
"Group.OwnershipTransfer.DescriptionShortInfo" = "This will transfer the full **owner rights** for **%1$@** to **%2$@**.";
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ extension ChatListControllerImpl {
|
|||
updatedPresentationData: nil,
|
||||
peer: chatPeer,
|
||||
member: user,
|
||||
onLeave: true,
|
||||
initialError: error,
|
||||
present: { c, a in
|
||||
presentController(c)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ import TelegramPresentationData
|
|||
import EdgeEffect
|
||||
|
||||
public final class ResizableSheetComponentEnvironment: Equatable {
|
||||
public struct BoundsUpdate {
|
||||
public let bounds: CGRect
|
||||
public let isInteractive: Bool
|
||||
}
|
||||
|
||||
public let theme: PresentationTheme
|
||||
public let statusBarHeight: CGFloat
|
||||
public let safeInsets: UIEdgeInsets
|
||||
|
|
@ -19,7 +24,7 @@ public final class ResizableSheetComponentEnvironment: Equatable {
|
|||
public let screenSize: CGSize
|
||||
public let regularMetricsSize: CGSize?
|
||||
public let dismiss: (Bool) -> Void
|
||||
public let boundsUpdated: ActionSlot<CGRect>
|
||||
public let boundsUpdated: ActionSlot<BoundsUpdate>
|
||||
|
||||
public init(
|
||||
theme: PresentationTheme,
|
||||
|
|
@ -32,7 +37,7 @@ public final class ResizableSheetComponentEnvironment: Equatable {
|
|||
screenSize: CGSize,
|
||||
regularMetricsSize: CGSize?,
|
||||
dismiss: @escaping (Bool) -> Void,
|
||||
boundsUpdated: ActionSlot<CGRect> = ActionSlot<CGRect>()
|
||||
boundsUpdated: ActionSlot<BoundsUpdate> = ActionSlot<BoundsUpdate>()
|
||||
) {
|
||||
self.theme = theme
|
||||
self.statusBarHeight = statusBarHeight
|
||||
|
|
@ -479,7 +484,7 @@ public final class ResizableSheetComponent<ChildEnvironmentType: Sendable & Equa
|
|||
|
||||
var bounds = self.scrollView.bounds
|
||||
bounds.size.width = itemLayout.fillingSize
|
||||
self.environment?.boundsUpdated.invoke(bounds)
|
||||
self.environment?.boundsUpdated.invoke(ResizableSheetComponentEnvironment.BoundsUpdate(bounds: bounds, isInteractive: self.scrollView.isTracking))
|
||||
}
|
||||
|
||||
private var didPlayAppearanceAnimation = false
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||
guard let strongSelf = self, let (layout, navigationBarHeight) = strongSelf.validLayout, strongSelf.listNode.scrollEnabled else {
|
||||
return
|
||||
}
|
||||
let overlap: CGFloat = 6.0
|
||||
let overlap: CGFloat = 0.0
|
||||
strongSelf.listOffset = max(0.0, offset)
|
||||
let headerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(0.0, offset + overlap)))
|
||||
listTransition.updateFrame(node: strongSelf.headerNode, frame: headerFrame)
|
||||
|
|
@ -940,7 +940,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||
}
|
||||
}
|
||||
|
||||
let overlap: CGFloat = 6.0
|
||||
let overlap: CGFloat = 0.0
|
||||
var topInset: CGFloat = layout.size.height - layout.intrinsicInsets.bottom - overlap
|
||||
if !self.isStoryLocation {
|
||||
topInset -= 100.0
|
||||
|
|
|
|||
|
|
@ -1109,6 +1109,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
|
|||
updatedPresentationData: updatedPresentationData,
|
||||
peer: peer,
|
||||
member: member,
|
||||
onLeave: false,
|
||||
initialError: error,
|
||||
present: { c, a in
|
||||
presentControllerImpl?(c, a)
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ private final class CraftGiftPageContent: Component {
|
|||
|
||||
self.craftStateDisposable = (component.craftContext.state
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
guard let self else {
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
self.craftState = state
|
||||
|
|
@ -297,6 +297,10 @@ private final class CraftGiftPageContent: Component {
|
|||
self.component?.externalState.giftsMap = self.giftMap
|
||||
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
if state.gifts.count < 18, case .ready(true, _) = state.dataState {
|
||||
component.craftContext.loadMore()
|
||||
}
|
||||
})
|
||||
|
||||
self.upgradePreviewDisposable.add((component.context.engine.payments.getStarGiftUpgradeAttributes(giftId: initialGiftItem.gift.giftId)
|
||||
|
|
@ -1622,9 +1626,31 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||
))
|
||||
} else {
|
||||
var buttonAnimatedItems: [AnimatedTextComponent.Item] = []
|
||||
buttonAnimatedItems.append(AnimatedTextComponent.Item(id: "percent", content: .number(Int(permilleValue / 10), minDigits: 1)))
|
||||
buttonAnimatedItems.append(AnimatedTextComponent.Item(id: "suffix", content: .text(environment.strings.Gift_Craft_SuccessChanceSuffix)))
|
||||
|
||||
let rawString = environment.strings.Gift_Craft_Crafting_SuccessChance("{p}").string
|
||||
var startIndex = rawString.startIndex
|
||||
while true {
|
||||
if let range = rawString.range(of: "{", range: startIndex ..< rawString.endIndex) {
|
||||
if range.lowerBound != startIndex {
|
||||
buttonAnimatedItems.append(AnimatedTextComponent.Item(id: AnyHashable(buttonAnimatedItems.count), content: .text(String(rawString[startIndex ..< range.lowerBound]))))
|
||||
}
|
||||
|
||||
startIndex = range.upperBound
|
||||
if let endRange = rawString.range(of: "}", range: startIndex ..< rawString.endIndex) {
|
||||
let controlString = rawString[range.upperBound ..< endRange.lowerBound]
|
||||
if controlString == "p" {
|
||||
buttonAnimatedItems.append(AnimatedTextComponent.Item(id: AnyHashable(buttonAnimatedItems.count), content: .number(Int(permilleValue / 10), minDigits: 1)))
|
||||
}
|
||||
startIndex = endRange.upperBound
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if startIndex != rawString.endIndex {
|
||||
buttonAnimatedItems.append(AnimatedTextComponent.Item(id: AnyHashable(buttonAnimatedItems.count), content: .text(String(rawString[startIndex ..< rawString.endIndex]))))
|
||||
}
|
||||
|
||||
buttonContent = AnyComponentWithIdentity(id: "craft", component: AnyComponent(
|
||||
VStack([
|
||||
AnyComponentWithIdentity(
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ final class SelectGiftPageContent: Component {
|
|||
let starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>
|
||||
let selectGift: (GiftItem) -> Void
|
||||
let dismiss: () -> Void
|
||||
let boundsUpdated: ActionSlot<CGRect>
|
||||
let boundsUpdated: ActionSlot<ResizableSheetComponentEnvironment.BoundsUpdate>
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
|
|
@ -47,7 +47,7 @@ final class SelectGiftPageContent: Component {
|
|||
starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>,
|
||||
selectGift: @escaping (GiftItem) -> Void,
|
||||
dismiss: @escaping () -> Void,
|
||||
boundsUpdated: ActionSlot<CGRect>
|
||||
boundsUpdated: ActionSlot<ResizableSheetComponentEnvironment.BoundsUpdate>
|
||||
) {
|
||||
self.context = context
|
||||
self.craftContext = craftContext
|
||||
|
|
@ -310,6 +310,13 @@ final class SelectGiftPageContent: Component {
|
|||
storeGiftsView.updateScrolling(bounds: bounds.offsetBy(dx: 0.0, dy: -contentHeight), interactive: interactive, transition: .immediate)
|
||||
}
|
||||
|
||||
let bottomContentOffset = max(0.0, contentHeight - bounds.origin.y - bounds.height)
|
||||
if interactive, bottomContentOffset < 800.0 {
|
||||
Queue.mainQueue().justDispatch {
|
||||
component.craftContext.loadMore()
|
||||
}
|
||||
}
|
||||
|
||||
return contentHeight
|
||||
}
|
||||
|
||||
|
|
@ -323,12 +330,12 @@ final class SelectGiftPageContent: Component {
|
|||
if self.component == nil {
|
||||
self.currentBounds = CGRect(origin: .zero, size: availableSize)
|
||||
|
||||
component.boundsUpdated.connect { [weak self] bounds in
|
||||
component.boundsUpdated.connect { [weak self] update in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.currentBounds = bounds
|
||||
let _ = self.updateScrolling(interactive: true, transition: .immediate)
|
||||
self.currentBounds = update.bounds
|
||||
let _ = self.updateScrolling(interactive: update.isInteractive, transition: .immediate)
|
||||
}
|
||||
|
||||
let initialGiftItem = GiftItem(
|
||||
|
|
@ -370,7 +377,9 @@ final class SelectGiftPageContent: Component {
|
|||
self.availableGifts = items
|
||||
self.giftMap = giftMap
|
||||
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -545,7 +554,7 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||
let sheet = Child(ResizableSheetComponent<EnvironmentType>.self)
|
||||
let animateOut = StoredActionSlot(Action<Void>.self)
|
||||
|
||||
let boundsUpdated = ActionSlot<CGRect>()
|
||||
let boundsUpdated = ActionSlot<ResizableSheetComponentEnvironment.BoundsUpdate>()
|
||||
|
||||
return { context in
|
||||
let component = context.component
|
||||
|
|
|
|||
|
|
@ -103,6 +103,15 @@ public final class GiftStoreContentComponent: Component {
|
|||
if lhs.gift != rhs.gift {
|
||||
return false
|
||||
}
|
||||
if lhs.safeInsets != rhs.safeInsets {
|
||||
return false
|
||||
}
|
||||
if lhs.statusBarHeight != rhs.statusBarHeight {
|
||||
return false
|
||||
}
|
||||
if lhs.navigationHeight != rhs.navigationHeight {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1543,17 +1543,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||
|
||||
self?.shareGift()
|
||||
})))
|
||||
|
||||
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 {
|
||||
|
||||
if let _ = arguments.canCraftDate {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_Craft, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Premium/Craft/Craft"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] c, _ in
|
||||
|
|
@ -5279,27 +5270,16 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||
var rightControlItems: [GlassControlGroupComponent.Item] = []
|
||||
if uniqueGift != nil && !showWearPreview && !isDismantled {
|
||||
if let _ = component.subject.arguments?.canCraftDate {
|
||||
var canCraft = false
|
||||
if let data = component.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 canCraft {
|
||||
rightControlItems.append(GlassControlGroupComponent.Item(
|
||||
id: AnyHashable("craft"),
|
||||
content: .icon("Premium/Craft"),
|
||||
action: { [weak state] in
|
||||
guard let state else {
|
||||
return
|
||||
}
|
||||
state.craftGift()
|
||||
rightControlItems.append(GlassControlGroupComponent.Item(
|
||||
id: AnyHashable("craft"),
|
||||
content: .icon("Premium/Craft"),
|
||||
action: { [weak state] in
|
||||
guard let state else {
|
||||
return
|
||||
}
|
||||
))
|
||||
}
|
||||
state.craftGift()
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
rightControlItems.append(GlassControlGroupComponent.Item(
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ private func confirmChannelOwnershipTransferController(
|
|||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||
peer: EnginePeer,
|
||||
member: TelegramUser,
|
||||
onLeave: Bool,
|
||||
present: @escaping (ViewController, Any?) -> Void,
|
||||
push: @escaping (ViewController) -> Void,
|
||||
completion: @escaping (EnginePeer.Id?) -> Void
|
||||
|
|
@ -184,7 +185,7 @@ private func confirmChannelOwnershipTransferController(
|
|||
var text: String
|
||||
if isGroup {
|
||||
title = presentationData.strings.Group_OwnershipTransfer_Title
|
||||
text = presentationData.strings.Group_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), EnginePeer.user(member).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
text = onLeave ? presentationData.strings.Group_OwnershipTransfer_DescriptionShortInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), EnginePeer.user(member).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string : presentationData.strings.Group_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), EnginePeer.user(member).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
} else {
|
||||
title = presentationData.strings.Channel_OwnershipTransfer_Title
|
||||
text = presentationData.strings.Channel_OwnershipTransfer_DescriptionInfo(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), EnginePeer.user(member).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
|
|
@ -211,6 +212,7 @@ public func channelOwnershipTransferController(
|
|||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||
peer: EnginePeer,
|
||||
member: TelegramUser,
|
||||
onLeave: Bool,
|
||||
initialError: ChannelOwnershipTransferError,
|
||||
present: @escaping (ViewController, Any?) -> Void,
|
||||
push: @escaping (ViewController) -> Void,
|
||||
|
|
@ -232,7 +234,7 @@ public func channelOwnershipTransferController(
|
|||
]
|
||||
switch initialError {
|
||||
case .requestPassword:
|
||||
return confirmChannelOwnershipTransferController(context: context, updatedPresentationData: updatedPresentationData, peer: peer, member: member, present: present, push: push, completion: completion)
|
||||
return confirmChannelOwnershipTransferController(context: context, updatedPresentationData: updatedPresentationData, peer: peer, member: member, onLeave: onLeave, present: present, push: push, completion: completion)
|
||||
case .twoStepAuthTooFresh, .authSessionTooFresh:
|
||||
text = text + strings.OwnershipTransfer_ComeBackLater
|
||||
case .twoStepAuthMissing:
|
||||
|
|
|
|||
|
|
@ -290,13 +290,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||
}
|
||||
}
|
||||
}
|
||||
if #available(iOS 13.0, *) {
|
||||
if self.presentationData.theme.overallDarkAppearance {
|
||||
webView.overrideUserInterfaceStyle = .dark
|
||||
} else {
|
||||
webView.overrideUserInterfaceStyle = .unspecified
|
||||
}
|
||||
|
||||
if self.presentationData.theme.overallDarkAppearance {
|
||||
webView.overrideUserInterfaceStyle = .dark
|
||||
} else {
|
||||
webView.overrideUserInterfaceStyle = .unspecified
|
||||
}
|
||||
|
||||
self.webView = webView
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
|
|
@ -1093,6 +1093,9 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||
guard let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
guard message.frameInfo.isMainFrame else {
|
||||
return
|
||||
}
|
||||
guard let body = message.body as? [String: Any] else {
|
||||
return
|
||||
}
|
||||
|
|
@ -2028,12 +2031,10 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||
self.updateHeaderBackgroundColor(transition: .immediate)
|
||||
self.sendThemeChangedEvent()
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
if self.presentationData.theme.overallDarkAppearance {
|
||||
self.webView?.overrideUserInterfaceStyle = .dark
|
||||
} else {
|
||||
self.webView?.overrideUserInterfaceStyle = .unspecified
|
||||
}
|
||||
if self.presentationData.theme.overallDarkAppearance {
|
||||
self.webView?.overrideUserInterfaceStyle = .dark
|
||||
} else {
|
||||
self.webView?.overrideUserInterfaceStyle = .unspecified
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ final class WebAppWebView: WKWebView {
|
|||
let contentController = WKUserContentController()
|
||||
|
||||
var handleScriptMessageImpl: ((WKScriptMessage) -> Void)?
|
||||
let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
|
||||
let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
||||
contentController.addUserScript(eventProxyScript)
|
||||
contentController.add(WeakGameScriptMessageHandler { message in
|
||||
handleScriptMessageImpl?(message)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"app": "12.3.3",
|
||||
"app": "12.4",
|
||||
"xcode": "26.2",
|
||||
"bazel": "8.4.2:45e9388abf21d1107e146ea366ad080eb93cb6a5f3a4a3b048f78de0bc3faffa",
|
||||
"macos": "26"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue