mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-28 02:45:58 +00:00
Stories
This commit is contained in:
parent
481419ced0
commit
6b330351e1
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1091,20 +1091,19 @@ public extension TelegramEngine {
|
|||||||
hasUnseen = peerState.maxReadId < lastEntry.id
|
hasUnseen = peerState.maxReadId < lastEntry.id
|
||||||
|
|
||||||
for item in itemsView.items {
|
for item in itemsView.items {
|
||||||
|
if case let .item(item) = item.value.get(Stories.StoredItem.self) {
|
||||||
if item.id > peerState.maxReadId {
|
if item.id > peerState.maxReadId {
|
||||||
unseenCount += 1
|
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 {
|
if item.media is TelegramMediaLiveStream {
|
||||||
hasLiveItems = true
|
hasLiveItems = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
var maxPendingTimestamp: Int32?
|
var maxPendingTimestamp: Int32?
|
||||||
if let localState = localState {
|
if let localState = localState {
|
||||||
for item in localState.items {
|
for item in localState.items {
|
||||||
@ -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
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user