This commit is contained in:
Isaac 2025-11-06 12:53:18 +04:00
parent 481419ced0
commit 6b330351e1
8 changed files with 86 additions and 35 deletions

View File

@ -37,9 +37,9 @@ extension ChatListControllerImpl {
} }
) )
tooltipScreen.tag = "no_auto_dismiss" tooltipScreen.tag = "no_auto_dismiss"
weak var tooltipScreenValue: UndoOverlayController? = tooltipScreen let tooltipScreenValue: UndoOverlayController? = tooltipScreen
self.currentTooltipUpdateTimer?.invalidate() self.currentTooltipUpdateTimer?.invalidate()
self.currentTooltipUpdateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in self.currentTooltipUpdateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self, weak tooltipScreenValue] _ in
guard let self else { guard let self else {
return return
} }

View File

@ -163,8 +163,8 @@ final class NetworkFrameworkTcpConnectionInterface: NSObject, MTTcpConnectionInt
connectTimeoutTimer.invalidate() connectTimeoutTimer.invalidate()
} }
weak var delegate = self.delegate let delegate = self.delegate
self.delegateQueue.async { self.delegateQueue.async { [weak delegate] in
if let delegate = delegate { if let delegate = delegate {
delegate.connectionInterfaceDidConnect() delegate.connectionInterfaceDidConnect()
} }
@ -221,9 +221,9 @@ final class NetworkFrameworkTcpConnectionInterface: NSObject, MTTcpConnectionInt
if requestChunkLength == 0 { if requestChunkLength == 0 {
self.currentReadRequest = nil self.currentReadRequest = nil
weak var delegate = self.delegate let delegate = self.delegate
let currentInterfaceIsWifi = self.currentInterfaceIsWifi let currentInterfaceIsWifi = self.currentInterfaceIsWifi
self.delegateQueue.async { self.delegateQueue.async { [weak delegate] in
if let delegate = delegate { if let delegate = delegate {
delegate.connectionInterfaceDidRead(currentReadRequest.data, withTag: currentReadRequest.request.tag, networkType: currentInterfaceIsWifi ? 0 : 1) delegate.connectionInterfaceDidRead(currentReadRequest.data, withTag: currentReadRequest.request.tag, networkType: currentInterfaceIsWifi ? 0 : 1)
} }
@ -249,8 +249,8 @@ final class NetworkFrameworkTcpConnectionInterface: NSObject, MTTcpConnectionInt
let tag = currentReadRequest.request.tag let tag = currentReadRequest.request.tag
let readCount = data.count let readCount = data.count
weak var delegate = self.delegate let delegate = self.delegate
self.delegateQueue.async { self.delegateQueue.async { [weak delegate] in
if let delegate = delegate { if let delegate = delegate {
delegate.connectionInterfaceDidReadPartialData(ofLength: UInt(readCount), tag: tag) delegate.connectionInterfaceDidReadPartialData(ofLength: UInt(readCount), tag: tag)
} }
@ -279,8 +279,8 @@ final class NetworkFrameworkTcpConnectionInterface: NSObject, MTTcpConnectionInt
if !self.reportedDisconnection { if !self.reportedDisconnection {
self.reportedDisconnection = true self.reportedDisconnection = true
weak var delegate = self.delegate let delegate = self.delegate
self.delegateQueue.async { self.delegateQueue.async { [weak delegate] in
if let delegate = delegate { if let delegate = delegate {
delegate.connectionInterfaceDidDisconnectWithError(error) delegate.connectionInterfaceDidDisconnectWithError(error)
} }

View File

@ -1091,16 +1091,15 @@ public extension TelegramEngine {
hasUnseen = peerState.maxReadId < lastEntry.id hasUnseen = peerState.maxReadId < lastEntry.id
for item in itemsView.items { for item in itemsView.items {
if item.id > peerState.maxReadId { if case let .item(item) = item.value.get(Stories.StoredItem.self) {
unseenCount += 1 if item.id > peerState.maxReadId {
unseenCount += 1
if case let .item(item) = item.value.get(Stories.StoredItem.self) {
if item.isCloseFriends { if item.isCloseFriends {
hasUnseenCloseFriends = true hasUnseenCloseFriends = true
} }
if item.media is TelegramMediaLiveStream { }
hasLiveItems = true if item.media is TelegramMediaLiveStream {
} hasLiveItems = true
} }
} }
} }
@ -1176,8 +1175,8 @@ public extension TelegramEngine {
} }
items.sort(by: { lhs, rhs in items.sort(by: { lhs, rhs in
let lhsUnseenOrPending = lhs.hasUnseen || lhs.hasPending let lhsUnseenOrPending = lhs.hasUnseen || lhs.hasLiveItems || lhs.hasPending
let rhsUnseenOrPending = rhs.hasUnseen || rhs.hasPending let rhsUnseenOrPending = rhs.hasUnseen || rhs.hasLiveItems || rhs.hasPending
if lhsUnseenOrPending != rhsUnseenOrPending { if lhsUnseenOrPending != rhsUnseenOrPending {
if lhsUnseenOrPending { if lhsUnseenOrPending {
@ -1255,7 +1254,7 @@ public extension TelegramEngine {
let _ = accountPeer let _ = accountPeer
let _ = storiesStateView let _ = storiesStateView
var sortedItems: [(peer: Peer, item: Stories.Item, hasUnseen: Bool, lastTimestamp: Int32)] = [] var sortedItems: [(peer: Peer, item: Stories.Item, hasUnseenOrLive: Bool, lastTimestamp: Int32)] = []
for peerId in storySubscriptionsView.peerIds { for peerId in storySubscriptionsView.peerIds {
guard let peerView = views.views[PostboxViewKey.basicPeer(peerId)] as? BasicPeerView else { guard let peerView = views.views[PostboxViewKey.basicPeer(peerId)] as? BasicPeerView else {
@ -1275,22 +1274,22 @@ public extension TelegramEngine {
let lastTimestamp = itemsView.items.last?.value.get(Stories.StoredItem.self)?.timestamp let lastTimestamp = itemsView.items.last?.value.get(Stories.StoredItem.self)?.timestamp
let peerState: Stories.PeerState? = stateView.value?.get(Stories.PeerState.self) let peerState: Stories.PeerState? = stateView.value?.get(Stories.PeerState.self)
var hasUnseen = false var hasUnseenOrLive = false
if let peerState = peerState { if let peerState = peerState {
if let item = itemsView.items.first(where: { $0.id > peerState.maxReadId }) { if let item = itemsView.items.first(where: { $0.id > peerState.maxReadId || $0.isLiveStream }) {
hasUnseen = true hasUnseenOrLive = true
nextItem = item.value.get(Stories.StoredItem.self) nextItem = item.value.get(Stories.StoredItem.self)
} }
} }
if let nextItem = nextItem, case let .item(item) = nextItem, let lastTimestamp = lastTimestamp { if let nextItem = nextItem, case let .item(item) = nextItem, let lastTimestamp = lastTimestamp {
sortedItems.append((peer, item, hasUnseen, lastTimestamp)) sortedItems.append((peer, item, hasUnseenOrLive, lastTimestamp))
} }
} }
sortedItems.sort(by: { lhs, rhs in sortedItems.sort(by: { lhs, rhs in
if lhs.hasUnseen != rhs.hasUnseen { if lhs.hasUnseenOrLive != rhs.hasUnseenOrLive {
if lhs.hasUnseen { if lhs.hasUnseenOrLive {
return true return true
} else { } else {
return false return false

View File

@ -419,6 +419,10 @@ public final class StoryLiveChatMessageComponent: Component {
if textLayout.numberOfLines > 1 || (component.message.isFromAdmin && !displayStarsAmountBackground) { if textLayout.numberOfLines > 1 || (component.message.isFromAdmin && !displayStarsAmountBackground) {
backgroundFrame.size.height = max(backgroundFrame.size.height, textFrame.maxY + 8.0 - backgroundOrigin.y) backgroundFrame.size.height = max(backgroundFrame.size.height, textFrame.maxY + 8.0 - backgroundOrigin.y)
} }
if let starsAmountTextSize, !displayStarsAmountBackground, let lastLineRect = textLayout.linesRects().last, textFrame.minX + lastLineRect.maxX > backgroundFrame.width - 8.0 - starsAmountTextSize.width {
backgroundFrame.size.height += starsAmountTextSize.height + 2.0
}
} }
if let starsAmountTextSize, let starsAmountTextView = self.starsAmountText?.view, let starsAmountIcon = self.starsAmountIcon { if let starsAmountTextSize, let starsAmountTextView = self.starsAmountText?.view, let starsAmountIcon = self.starsAmountIcon {
@ -431,7 +435,7 @@ public final class StoryLiveChatMessageComponent: Component {
starsAmountTextFrame = CGRect(origin: CGPoint(x: starsAmountBackgroundFrame.maxX - starsAmountTextSize.width - 5.0, y: starsAmountBackgroundFrame.minY + UIScreenPixel + floor((starsAmountBackgroundFrame.height - starsAmountTextSize.height) * 0.5)), size: starsAmountTextSize) starsAmountTextFrame = CGRect(origin: CGPoint(x: starsAmountBackgroundFrame.maxX - starsAmountTextSize.width - 5.0, y: starsAmountBackgroundFrame.minY + UIScreenPixel + floor((starsAmountBackgroundFrame.height - starsAmountTextSize.height) * 0.5)), size: starsAmountTextSize)
} else { } else {
starsAmountTextFrame = CGRect(origin: CGPoint(x: textFrame.maxX - starsAmountTextSize.width - 1.0, y: textFrame.maxY - starsAmountTextSize.height + 1.0), size: starsAmountTextSize) starsAmountTextFrame = CGRect(origin: CGPoint(x: backgroundFrame.maxX - 8.0 - starsAmountTextSize.width, y: backgroundFrame.maxY - starsAmountTextSize.height - 8.0), size: starsAmountTextSize)
} }
if starsAmountTextView.superview == nil { if starsAmountTextView.superview == nil {

View File

@ -212,9 +212,12 @@ private final class PinnedBarMessageComponent: Component {
self.backgroundView.tintColor = baseColor.withMultipliedBrightnessBy(0.7) self.backgroundView.tintColor = baseColor.withMultipliedBrightnessBy(0.7)
self.foregroundView.tintColor = baseColor self.foregroundView.tintColor = baseColor
let timestamp = CFAbsoluteTimeGetCurrent() let timestamp = CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970
let currentDuration = max(0.0, timestamp - Double(component.message.date)) let currentDuration = max(0.0, timestamp - Double(component.message.date))
let timeFraction: CGFloat = 1.0 - min(1.0, currentDuration / Double(component.message.lifetime)) var timeFraction: CGFloat = 1.0 - min(1.0, currentDuration / Double(component.message.lifetime))
if case .local = component.message.id.space {
timeFraction = 1.0
}
let backgroundFrame = CGRect(origin: CGPoint(), size: size) let backgroundFrame = CGRect(origin: CGPoint(), size: size)
transition.setFrame(view: self.backgroundView, frame: backgroundFrame) transition.setFrame(view: self.backgroundView, frame: backgroundFrame)

View File

@ -1756,6 +1756,9 @@ public final class StoryItemSetContainerComponent: Component {
displayFooter = true displayFooter = true
displayFooterViews = false displayFooterViews = false
} }
if case .liveStream = component.slice.item.storyItem.media {
displayFooter = false
}
if component.slice.item.storyItem.isForwardingDisabled { if component.slice.item.storyItem.isForwardingDisabled {
canShare = false canShare = false
} }

View File

@ -3529,9 +3529,9 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
} }
) )
tooltipScreen.tag = "no_auto_dismiss" tooltipScreen.tag = "no_auto_dismiss"
weak var tooltipScreenValue: UndoOverlayController? = tooltipScreen let tooltipScreenValue: UndoOverlayController? = tooltipScreen
self.currentTooltipUpdateTimer?.invalidate() self.currentTooltipUpdateTimer?.invalidate()
self.currentTooltipUpdateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self, weak view] _ in self.currentTooltipUpdateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self, weak view, weak tooltipScreenValue] _ in
guard let self, let view, let component = view.component else { guard let self, let view, let component = view.component else {
return return
} }

View File

@ -42,6 +42,7 @@ import Photos
import GlassBarButtonComponent import GlassBarButtonComponent
import BundleIconComponent import BundleIconComponent
import LottieComponent import LottieComponent
import CryptoKit
private let durgerKingBotIds: [Int64] = [5104055776, 2200339955] private let durgerKingBotIds: [Int64] = [5104055776, 2200339955]
@ -426,6 +427,47 @@ public final class WebAppController: ViewController, AttachmentContainable {
webView.scrollView.insertSubview(self.topOverscrollNode.view, at: 0) webView.scrollView.insertSubview(self.topOverscrollNode.view, at: 0)
} }
private func load(url: URL) {
#if DEBUG
if "".isEmpty {
if #available(iOS 16.0, *) {
let documentsPath = URL.documentsDirectory.path(percentEncoded: false)
var hasher = SHA256()
var urlString = url.absoluteString
if let range = urlString.firstRange(of: "#") {
urlString.removeSubrange(range.lowerBound...)
}
hasher.update(data: urlString.data(using: .utf8)!)
let digest = Data(hasher.finalize())
let urlHash = hexString(digest)
let cachedFilePath = documentsPath.appending("\(urlHash).bin")
Task {
do {
let data: Data
if let cachedData = try? Data(contentsOf: URL(fileURLWithPath: cachedFilePath)) {
data = cachedData
print("Loaded from cache at \(cachedFilePath)")
} else {
let (loadedData, _) = try await URLSession.shared.data(from: url)
data = loadedData
try loadedData.write(to: URL(fileURLWithPath: cachedFilePath), options: .atomic)
}
self.webView?.load(data, mimeType: "text/html", characterEncodingName: "utf-8", baseURL: url)
} catch let e {
print("\(e)")
}
}
}
return
}
#endif
self.webView?.load(URLRequest(url: url))
}
func setupWebView() { func setupWebView() {
guard let controller = self.controller else { guard let controller = self.controller else {
return return
@ -434,7 +476,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
if let url = controller.url, controller.source != .menu { if let url = controller.url, controller.source != .menu {
self.queryId = controller.queryId self.queryId = controller.queryId
if let parsedUrl = URL(string: url) { if let parsedUrl = URL(string: url) {
self.webView?.load(URLRequest(url: parsedUrl)) self.load(url: parsedUrl)
} }
if let keepAliveSignal = controller.keepAliveSignal { if let keepAliveSignal = controller.keepAliveSignal {
self.keepAliveDisposable = (keepAliveSignal self.keepAliveDisposable = (keepAliveSignal
@ -457,7 +499,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
} }
if let parsedUrl = URL(string: result.url) { if let parsedUrl = URL(string: result.url) {
strongSelf.queryId = result.queryId strongSelf.queryId = result.queryId
strongSelf.webView?.load(URLRequest(url: parsedUrl)) strongSelf.load(url: parsedUrl)
} }
}) })
} else { } else {
@ -477,7 +519,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
return return
} }
self.controller?.titleView?.title = WebAppTitle(title: botApp.title, counter: self.presentationData.strings.WebApp_Miniapp, isVerified: controller.botVerified) self.controller?.titleView?.title = WebAppTitle(title: botApp.title, counter: self.presentationData.strings.WebApp_Miniapp, isVerified: controller.botVerified)
self.webView?.load(URLRequest(url: parsedUrl)) self.load(url: parsedUrl)
}) })
}) })
} else { } else {
@ -487,7 +529,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
return return
} }
strongSelf.queryId = result.queryId strongSelf.queryId = result.queryId
strongSelf.webView?.load(URLRequest(url: parsedUrl)) strongSelf.load(url: parsedUrl)
if let keepAliveSignal = result.keepAliveSignal { if let keepAliveSignal = result.keepAliveSignal {
strongSelf.keepAliveDisposable = (keepAliveSignal strongSelf.keepAliveDisposable = (keepAliveSignal