From d6052431ca15ca3bb26c5e0a1bccd73665946090 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 16 Jul 2024 16:44:04 +0400 Subject: [PATCH 1/3] Update API --- submodules/TelegramApi/Sources/Api0.swift | 4 ++-- submodules/TelegramApi/Sources/Api5.swift | 18 +++++++++++------- .../Sources/ApiUtils/TelegramMediaFile.swift | 3 ++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index a534054d76..95280d53e2 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -242,7 +242,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1744710921] = { return Api.DocumentAttribute.parse_documentAttributeHasStickers($0) } dict[1815593308] = { return Api.DocumentAttribute.parse_documentAttributeImageSize($0) } dict[1662637586] = { return Api.DocumentAttribute.parse_documentAttributeSticker($0) } - dict[-745541182] = { return Api.DocumentAttribute.parse_documentAttributeVideo($0) } + dict[389652397] = { return Api.DocumentAttribute.parse_documentAttributeVideo($0) } dict[761606687] = { return Api.DraftMessage.parse_draftMessage($0) } dict[453805082] = { return Api.DraftMessage.parse_draftMessageEmpty($0) } dict[-1764723459] = { return Api.EmailVerification.parse_emailVerificationApple($0) } @@ -1398,7 +1398,7 @@ public extension Api { return parser(reader) } else { - telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found") + telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found") return nil } } diff --git a/submodules/TelegramApi/Sources/Api5.swift b/submodules/TelegramApi/Sources/Api5.swift index b8ae224638..bd121a4a0b 100644 --- a/submodules/TelegramApi/Sources/Api5.swift +++ b/submodules/TelegramApi/Sources/Api5.swift @@ -1473,7 +1473,7 @@ public extension Api { case documentAttributeHasStickers case documentAttributeImageSize(w: Int32, h: Int32) case documentAttributeSticker(flags: Int32, alt: String, stickerset: Api.InputStickerSet, maskCoords: Api.MaskCoords?) - case documentAttributeVideo(flags: Int32, duration: Double, w: Int32, h: Int32, preloadPrefixSize: Int32?) + case documentAttributeVideo(flags: Int32, duration: Double, w: Int32, h: Int32, preloadPrefixSize: Int32?, videoStartTs: Double?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -1529,15 +1529,16 @@ public extension Api { stickerset.serialize(buffer, true) if Int(flags) & Int(1 << 0) != 0 {maskCoords!.serialize(buffer, true)} break - case .documentAttributeVideo(let flags, let duration, let w, let h, let preloadPrefixSize): + case .documentAttributeVideo(let flags, let duration, let w, let h, let preloadPrefixSize, let videoStartTs): if boxed { - buffer.appendInt32(-745541182) + buffer.appendInt32(389652397) } serializeInt32(flags, buffer: buffer, boxed: false) serializeDouble(duration, buffer: buffer, boxed: false) serializeInt32(w, buffer: buffer, boxed: false) serializeInt32(h, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 2) != 0 {serializeInt32(preloadPrefixSize!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} break } } @@ -1558,8 +1559,8 @@ public extension Api { return ("documentAttributeImageSize", [("w", w as Any), ("h", h as Any)]) case .documentAttributeSticker(let flags, let alt, let stickerset, let maskCoords): return ("documentAttributeSticker", [("flags", flags as Any), ("alt", alt as Any), ("stickerset", stickerset as Any), ("maskCoords", maskCoords as Any)]) - case .documentAttributeVideo(let flags, let duration, let w, let h, let preloadPrefixSize): - return ("documentAttributeVideo", [("flags", flags as Any), ("duration", duration as Any), ("w", w as Any), ("h", h as Any), ("preloadPrefixSize", preloadPrefixSize as Any)]) + case .documentAttributeVideo(let flags, let duration, let w, let h, let preloadPrefixSize, let videoStartTs): + return ("documentAttributeVideo", [("flags", flags as Any), ("duration", duration as Any), ("w", w as Any), ("h", h as Any), ("preloadPrefixSize", preloadPrefixSize as Any), ("videoStartTs", videoStartTs as Any)]) } } @@ -1671,13 +1672,16 @@ public extension Api { _4 = reader.readInt32() var _5: Int32? if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } + var _6: Double? + if Int(_1!) & Int(1 << 4) != 0 {_6 = reader.readDouble() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.DocumentAttribute.documentAttributeVideo(flags: _1!, duration: _2!, w: _3!, h: _4!, preloadPrefixSize: _5) + let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.DocumentAttribute.documentAttributeVideo(flags: _1!, duration: _2!, w: _3!, h: _4!, preloadPrefixSize: _5, videoStartTs: _6) } else { return nil diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index 9daed9bc01..c94ec75593 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift @@ -99,7 +99,8 @@ func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAtt result.append(.ImageSize(size: PixelDimensions(width: w, height: h))) case .documentAttributeAnimated: result.append(.Animated) - case let .documentAttributeVideo(flags, duration, w, h, preloadSize): + case let .documentAttributeVideo(flags, duration, w, h, preloadSize, videoStartTime): + let _ = videoStartTime var videoFlags = TelegramMediaVideoFlags() if (flags & (1 << 0)) != 0 { videoFlags.insert(.instantRoundVideo) From 3fc1dd74551f4f4e52cb76ec5dc290bc1832cddf Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 16 Jul 2024 16:45:16 +0400 Subject: [PATCH 2/3] Various improvements --- .../CameraScreen/Sources/CameraScreen.swift | 7 +- .../Sources/StarsTransactionScreen.swift | 107 ++++++++++++++---- .../StarsTransactionsListPanelComponent.swift | 14 ++- .../Components/VideoMessageCameraScreen/BUILD | 1 + .../Sources/VideoMessageCameraScreen.swift | 64 ++++++++--- .../Resources/Animations/roundFlash_off.json | 1 + .../Resources/Animations/roundFlash_on.json | 1 + 7 files changed, 156 insertions(+), 39 deletions(-) create mode 100644 submodules/TelegramUI/Resources/Animations/roundFlash_off.json create mode 100644 submodules/TelegramUI/Resources/Animations/roundFlash_on.json diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index 55084110b9..6baabab4ba 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -847,7 +847,12 @@ private final class CameraScreenComponent: CombinedComponent { .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) .scale(1.5 - component.cameraState.flashTintSize * 0.5) .appear(.default(alpha: true)) - .disappear(.default(alpha: true)) + .disappear(ComponentTransition.Disappear({ view, transition, completion in + view.superview?.sendSubviewToBack(view) + transition.setAlpha(view: view, alpha: 0.0, completion: { _ in + completion() + }) + })) ) if !state.isTakingPhoto { diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift index 1ec2ead77e..5a667fe7fb 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift @@ -140,6 +140,8 @@ private final class StarsTransactionSheetContent: CombinedComponent { let refundBackgound = Child(RoundedRectangle.self) let refundText = Child(MultilineTextComponent.self) + let spaceRegex = try? NSRegularExpression(pattern: "\\[(.*?)\\]", options: []) + return { context in let environment = context.environment[ViewControllerComponentContainer.Environment.self].value let controller = environment.controller @@ -176,11 +178,13 @@ private final class StarsTransactionSheetContent: CombinedComponent { let titleText: String let amountText: String - let descriptionText: String + var descriptionText: String let additionalText: String let buttonText: String let count: Int64 + var countIsGeneric = false + var countOnTop = false let transactionId: String? let date: Int32 let via: String? @@ -199,6 +203,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { titleText = "Received Gift" descriptionText = "Use Stars to unlock content and services on Telegram. [See Examples >]()" count = transaction.count + countOnTop = true transactionId = transaction.id via = nil messageId = nil @@ -317,9 +322,13 @@ private final class StarsTransactionSheetContent: CombinedComponent { let incoming = message.flags.contains(.Incoming) titleText = incoming ? "Received Gift" : "Sent Gift" let peerName = state.peerMap[message.id.peerId]?.compactDisplayTitle ?? "" - descriptionText = incoming ? "Use Stars to unlock content and services on Telegram. [See Examples >]()" : "With Stars, \(peerName) will be able to unlock content and services on Telegram.\n[See Examples >]()" + descriptionText = incoming ? "Use Stars to unlock content and services on Telegram. [See Examples >]()" : "With Stars, \(peerName) will be able to unlock content and services on Telegram. [See Examples >]()" if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .giftStars(_, _, countValue, _, _, _) = action.action { - count = !incoming ? -countValue : countValue + count = countValue + if !incoming { + countIsGeneric = true + } + countOnTop = true transactionId = nil } else { fatalError() @@ -327,7 +336,11 @@ private final class StarsTransactionSheetContent: CombinedComponent { via = nil messageId = nil date = message.timestamp - toPeer = state.peerMap[message.id.peerId] + if message.id.peerId.id._internalGetInt64Value() == 777000 { + toPeer = nil + } else { + toPeer = state.peerMap[message.id.peerId] + } transactionPeer = nil media = [] photo = nil @@ -335,12 +348,31 @@ private final class StarsTransactionSheetContent: CombinedComponent { isGift = true delayedCloseOnOpenPeer = false } + if let spaceRegex { + let nsRange = NSRange(descriptionText.startIndex..., in: descriptionText) + let matches = spaceRegex.matches(in: descriptionText, options: [], range: nsRange) + var modifiedString = descriptionText + + for match in matches.reversed() { + let matchRange = Range(match.range, in: descriptionText)! + let matchedSubstring = String(descriptionText[matchRange]) + let replacedSubstring = matchedSubstring.replacingOccurrences(of: " ", with: "\u{00A0}") + modifiedString.replaceSubrange(matchRange, with: replacedSubstring) + } + descriptionText = modifiedString + } let formattedAmount = presentationStringsFormattedNumber(abs(Int32(count)), dateTimeFormat.groupingSeparator) - if count < 0 { + let countColor: UIColor + if countIsGeneric { + amountText = "\(formattedAmount)" + countColor = theme.list.itemPrimaryTextColor + } else if count < 0 { amountText = "- \(formattedAmount)" + countColor = theme.list.itemDestructiveColor } else { amountText = "+ \(formattedAmount)" + countColor = theme.list.itemDisclosureActions.constructive.fillColor } additionalText = strings.Stars_Transaction_Terms buttonText = strings.Common_OK @@ -389,7 +421,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { transition: .immediate ) - let amountAttributedText = NSMutableAttributedString(string: amountText, font: Font.semibold(17.0), textColor: amountText.hasPrefix("-") ? theme.list.itemDestructiveColor : theme.list.itemDisclosureActions.constructive.fillColor) + let amountAttributedText = NSMutableAttributedString(string: amountText, font: Font.semibold(17.0), textColor: countColor) let amount = amount.update( component: BalancedTextComponent( text: .plain(amountAttributedText), @@ -415,10 +447,33 @@ private final class StarsTransactionSheetContent: CombinedComponent { let tableLinkColor = theme.list.itemAccentColor var tableItems: [TableComponent.Item] = [] - if let toPeer { + if isGift, toPeer == nil { + tableItems.append(.init( + id: "from", + title: strings.Stars_Transaction_From, + component: AnyComponent( + Button( + content: AnyComponent( + PeerCellComponent( + context: component.context, + theme: theme, + peer: nil + ) + ), + action: { + let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } + component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: strings.Stars_Transaction_FragmentUnknown_URL, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {}) + Queue.mainQueue().after(1.0, { + component.cancel(false) + }) + } + ) + ) + )) + } else if let toPeer { tableItems.append(.init( id: "to", - title: count < 0 ? strings.Stars_Transaction_To : strings.Stars_Transaction_From, + title: count < 0 || countIsGeneric ? strings.Stars_Transaction_To : strings.Stars_Transaction_From, component: AnyComponent( Button( content: AnyComponent( @@ -592,12 +647,14 @@ private final class StarsTransactionSheetContent: CombinedComponent { var originY: CGFloat = 0.0 originY += star.size.height - 23.0 + var descriptionSize: CGSize = .zero if !descriptionText.isEmpty { if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== environment.theme { state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: linkColor)!, theme) } let textFont = Font.regular(15.0) + let textColor = countOnTop ? theme.list.itemPrimaryTextColor : textColor let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: textFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: linkColor), linkAttribute: { contents in return (TelegramTextAttributes.URL, contents) }) @@ -609,13 +666,19 @@ private final class StarsTransactionSheetContent: CombinedComponent { component: MultilineTextComponent( text: .plain(attributedString), horizontalAlignment: .center, - maximumNumberOfLines: 3 + maximumNumberOfLines: 5, + lineSpacing: 0.2 ), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude), transition: .immediate ) + descriptionSize = description.size + var descriptionOrigin = originY + if countOnTop { + descriptionOrigin += amount.size.height + 13.0 + } context.add(description - .position(CGPoint(x: context.availableSize.width / 2.0, y: originY + description.size.height / 2.0)) + .position(CGPoint(x: context.availableSize.width / 2.0, y: descriptionOrigin + description.size.height / 2.0)) ) originY += description.size.height + 10.0 } @@ -654,14 +717,20 @@ private final class StarsTransactionSheetContent: CombinedComponent { ) } + var amountOrigin = originY + if countOnTop { + amountOrigin -= descriptionSize.height + 10.0 + originY += amount.size.height + 26.0 + } else { + originY += amount.size.height + 20.0 + } context.add(amount - .position(CGPoint(x: amountOriginX + amount.size.width / 2.0, y: originY + amount.size.height / 2.0)) + .position(CGPoint(x: amountOriginX + amount.size.width / 2.0, y: amountOrigin + amount.size.height / 2.0)) ) context.add(amountStar - .position(CGPoint(x: amountOriginX + amount.size.width + amountSpacing + amountStar.size.width / 2.0, y: originY + amountStar.size.height / 2.0)) + .position(CGPoint(x: amountOriginX + amount.size.width + amountSpacing + amountStar.size.width / 2.0, y: amountOrigin + amountStar.size.height / 2.0)) ) - originY += amount.size.height + 20.0 context.add(table .position(CGPoint(x: context.availableSize.width / 2.0, y: originY + table.size.height / 2.0)) @@ -1229,9 +1298,9 @@ private final class TableComponent: CombinedComponent { private final class PeerCellComponent: Component { let context: AccountContext let theme: PresentationTheme - let peer: EnginePeer + let peer: EnginePeer? - init(context: AccountContext, theme: PresentationTheme, peer: EnginePeer) { + init(context: AccountContext, theme: PresentationTheme, peer: EnginePeer?) { self.context = context self.theme = theme self.peer = peer @@ -1274,12 +1343,12 @@ private final class PeerCellComponent: Component { let peerName: String let peer: StarsContext.State.Transaction.Peer - if component.peer.id.namespace == Namespaces.Peer.CloudUser && component.peer.id.id._internalGetInt64Value() == 777000 { + if let peerValue = component.peer { + peerName = peerValue.compactDisplayTitle + peer = .peer(peerValue) + } else { peerName = "Unknown User" peer = .fragment - } else { - peerName = component.peer.compactDisplayTitle - peer = .peer(component.peer) } let avatarNaturalSize = self.avatar.update( diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsListPanelComponent.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsListPanelComponent.swift index e00e0c4e18..7fb087911e 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsListPanelComponent.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsListPanelComponent.swift @@ -220,10 +220,6 @@ final class StarsTransactionsListPanelComponent: Component { if item.flags.contains(.isGift) { //TODO:localize itemSubtitle = "Received Gift" - if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 { - itemTitle = "Unknown User" - itemPeer = .fragment - } } else { itemSubtitle = nil } @@ -236,8 +232,14 @@ final class StarsTransactionsListPanelComponent: Component { itemSubtitle = environment.strings.Stars_Intro_Transaction_GoogleTopUp_Subtitle case .fragment: if component.isAccount { - itemTitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Title - itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Subtitle + if item.flags.contains(.isGift) { + itemTitle = "Unknown User" + itemSubtitle = "Received Gift" + itemPeer = .fragment + } else { + itemTitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Title + itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Subtitle + } } else { itemTitle = environment.strings.Stars_Intro_Transaction_FragmentWithdrawal_Title itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentWithdrawal_Subtitle diff --git a/submodules/TelegramUI/Components/VideoMessageCameraScreen/BUILD b/submodules/TelegramUI/Components/VideoMessageCameraScreen/BUILD index 2d431411f1..d39746aa69 100644 --- a/submodules/TelegramUI/Components/VideoMessageCameraScreen/BUILD +++ b/submodules/TelegramUI/Components/VideoMessageCameraScreen/BUILD @@ -41,6 +41,7 @@ swift_library( "//submodules/TelegramAudio", "//submodules/ChatSendMessageActionUI", "//submodules/TelegramUI/Components/ChatControllerInteraction", + "//submodules/TelegramUI/Components/LottieComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift index 1848125e56..4c67fe5171 100644 --- a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift +++ b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift @@ -29,6 +29,7 @@ import LegacyMediaPickerUI import TelegramAudio import ChatSendMessageActionUI import ChatControllerInteraction +import LottieComponent struct CameraState: Equatable { enum Recording: Equatable { @@ -68,7 +69,7 @@ struct CameraState: Equatable { } func updatedFlashMode(_ flashMode: Camera.FlashMode) -> CameraState { - return CameraState(position: self.position, flashMode: flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, flashTintSize: self.flashTintSize, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled, isViewOnceEnabled: self.isViewOnceEnabled) + return CameraState(position: self.position, flashMode: flashMode, flashModeDidChange: self.flashMode != flashMode, flashTint: self.flashTint, flashTintSize: self.flashTintSize, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled, isViewOnceEnabled: self.isViewOnceEnabled) } func updatedFlashTint(_ flashTint: FlashTint) -> CameraState { @@ -473,6 +474,8 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { let recordMoreButton = Child(PlainButtonComponent.self) let muteIcon = Child(ZStack.self) + + let flashAction = ActionSlot() return { context in let environment = context.environment[ViewControllerComponentContainer.Environment.self].value @@ -524,7 +527,12 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) .scale(1.5 - component.cameraState.flashTintSize * 0.5) .appear(.default(alpha: true)) - .disappear(.default(alpha: true)) + .disappear(ComponentTransition.Disappear({ view, transition, completion in + view.superview?.sendSubviewToBack(view) + transition.setAlpha(view: view, alpha: 0.0, completion: { _ in + completion() + }) + })) ) } @@ -557,23 +565,53 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { .disappear(.default(scale: true, alpha: true)) ) + let flashContentComponent: AnyComponentWithIdentity + if "".isEmpty { + let flashIconName: String + switch component.cameraState.flashMode { + case .off: + flashIconName = "roundFlash_off" + case .on: + flashIconName = "roundFlash_on" + default: + flashIconName = "roundFlash_off" + } + + flashContentComponent = AnyComponentWithIdentity( + id: "animatedIcon", + component: AnyComponent( + LottieComponent( + content: LottieComponent.AppBundleContent(name: flashIconName), + color: environment.theme.list.itemAccentColor, + startingPosition: !component.cameraState.flashModeDidChange ? .end : .begin, + size: CGSize(width: 40.0, height: 40.0), + loop: false, + playOnce: flashAction + ) + ) + ) + } else { + flashContentComponent = AnyComponentWithIdentity( + id: "staticIcon", + component: AnyComponent( + Image( + image: state.image(.flash, theme: environment.theme), + tintColor: environment.theme.list.itemAccentColor, + size: CGSize(width: 30.0, height: 30.0) + ) + ) + ) + } + let flashButton = flashButton.update( component: CameraButton( - content: AnyComponentWithIdentity( - id: "flash", - component: AnyComponent( - Image( - image: state.image(.flash, theme: environment.theme), - tintColor: environment.theme.list.itemAccentColor, - size: CGSize(width: 30.0, height: 30.0) - ) - ) - ), + content: flashContentComponent, minSize: CGSize(width: 44.0, height: 44.0), isExclusive: false, action: { [weak state] in if let state { state.toggleFlashMode() + flashAction.invoke(Void()) } } ), @@ -581,7 +619,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { transition: context.transition ) context.add(flashButton - .position(CGPoint(x: flipButton.size.width + 8.0 + flashButton.size.width / 2.0 + 8.0, y: availableSize.height - flashButton.size.height / 2.0 - 8.0)) + .position(CGPoint(x: flipButton.size.width + 8.0 + flashButton.size.width / 2.0 + 11.0, y: availableSize.height - flashButton.size.height / 2.0 - 8.0)) .appear(.default(scale: true, alpha: true)) .disappear(.default(scale: true, alpha: true)) ) diff --git a/submodules/TelegramUI/Resources/Animations/roundFlash_off.json b/submodules/TelegramUI/Resources/Animations/roundFlash_off.json new file mode 100644 index 0000000000..f4ca7a5f7c --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/roundFlash_off.json @@ -0,0 +1 @@ +{"v":"5.12.1","fr":60,"ip":0,"op":30,"w":120,"h":120,"nm":"flashoff","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"icon","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[59.063,65.062,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[9.688,9.688],[-9.688,-9.688]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.251],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":20,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Union","tt":2,"tp":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[58.673,60.014,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.502,0.544],[0,0],[0.336,-0.874],[0,0],[0,0],[0.502,-0.544],[0,0],[-0.336,0.874],[0,0],[0,0]],"o":[[0,0],[0.635,-0.688],[0,0],[0,0],[0.741,0],[0,0],[-0.635,0.688],[0,0],[0,0],[-0.741,0]],"v":[[-6.331,0.339],[3.46,-10.268],[4.877,-9.386],[1.946,-1.765],[5.706,-1.765],[6.331,-0.339],[-3.46,10.268],[-4.877,9.386],[-1.946,1.765],[-5.706,1.765]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[61.875,62.25,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[10,10],[-10,-10]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"icon","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.251],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":20,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/roundFlash_on.json b/submodules/TelegramUI/Resources/Animations/roundFlash_on.json new file mode 100644 index 0000000000..1ca8dba179 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/roundFlash_on.json @@ -0,0 +1 @@ +{"v":"5.12.1","fr":60,"ip":0,"op":30,"w":120,"h":120,"nm":"flashon","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"icon","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[59.063,65.062,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[9.688,9.688],[-9.688,-9.688]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.244],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"icon","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Union","tt":2,"tp":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[58.673,60.014,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.502,0.544],[0,0],[0.336,-0.874],[0,0],[0,0],[0.502,-0.544],[0,0],[-0.336,0.874],[0,0],[0,0]],"o":[[0,0],[0.635,-0.688],[0,0],[0,0],[0.741,0],[0,0],[-0.635,0.688],[0,0],[0,0],[-0.741,0]],"v":[[-6.331,0.339],[3.46,-10.268],[4.877,-9.386],[1.946,-1.765],[5.706,-1.765],[6.331,-0.339],[-3.46,10.268],[-4.877,9.386],[-1.946,1.765],[-5.706,1.765]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[61.875,62.25,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[10,10],[-10,-10]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"icon","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.244],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":20,"s":[100]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}} \ No newline at end of file From d23c90ea7d774d7dd075de7e833644bf222cf86d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 16 Jul 2024 16:47:42 +0400 Subject: [PATCH 3/3] Fix build --- .../Sources/PendingMessages/PendingMessageUploadedContent.swift | 2 +- .../Sources/TelegramEngine/Stickers/ImportStickers.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift index f76bc6d185..0ec84b8642 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift @@ -716,7 +716,7 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF flags |= (1 << 3) } - attributes.append(.documentAttributeVideo(flags: flags, duration: duration, w: Int32(size.width), h: Int32(size.height), preloadPrefixSize: preloadSize)) + attributes.append(.documentAttributeVideo(flags: flags, duration: duration, w: Int32(size.width), h: Int32(size.height), preloadPrefixSize: preloadSize, videoStartTs: nil)) case let .Audio(isVoice, duration, title, performer, waveform): var flags: Int32 = 0 if isVoice { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift index fb0878a5ae..ac6ed07c33 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift @@ -80,7 +80,7 @@ func _internal_uploadSticker(account: Account, peer: Peer, resource: MediaResour var attributes: [Api.DocumentAttribute] = [] attributes.append(.documentAttributeSticker(flags: 0, alt: alt, stickerset: .inputStickerSetEmpty, maskCoords: nil)) if let duration { - attributes.append(.documentAttributeVideo(flags: 0, duration: duration, w: dimensions.width, h: dimensions.height, preloadPrefixSize: nil)) + attributes.append(.documentAttributeVideo(flags: 0, duration: duration, w: dimensions.width, h: dimensions.height, preloadPrefixSize: nil, videoStartTs: nil)) } attributes.append(.documentAttributeImageSize(w: dimensions.width, h: dimensions.height)) return account.network.request(Api.functions.messages.uploadMedia(flags: 0, businessConnectionId: nil, peer: inputPeer, media: Api.InputMedia.inputMediaUploadedDocument(flags: flags, file: file, thumb: thumbnailFile, mimeType: mimeType, attributes: attributes, stickers: nil, ttlSeconds: nil)))