mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Youtube player fixes
This commit is contained in:
parent
7fb0b48ded
commit
c899d1dfa7
@ -4098,7 +4098,7 @@ Unused sets are archived when you add more.";
|
|||||||
|
|
||||||
"GroupPermission.PermissionGloballyDisabled" = "This permission is disabled in this group.";
|
"GroupPermission.PermissionGloballyDisabled" = "This permission is disabled in this group.";
|
||||||
|
|
||||||
"ChannelInfo.Stats" = "Statistics";
|
"ChannelInfo.Stats" = "View Statistics";
|
||||||
|
|
||||||
"Conversation.PressVolumeButtonForSound" = "Press volume button\nto unmute the video";
|
"Conversation.PressVolumeButtonForSound" = "Press volume button\nto unmute the video";
|
||||||
|
|
||||||
@ -5813,3 +5813,5 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
"Channel.CommentsGroup.HeaderGroupSet" = "%@ is linking the group as it's discussion board.";
|
"Channel.CommentsGroup.HeaderGroupSet" = "%@ is linking the group as it's discussion board.";
|
||||||
|
|
||||||
"RepliesChat.DescriptionText" = "This chat helps you keep track of replies to your comments in Channels.";
|
"RepliesChat.DescriptionText" = "This chat helps you keep track of replies to your comments in Channels.";
|
||||||
|
|
||||||
|
"Conversation.ContextViewStats" = "View Statistics";
|
||||||
|
@ -1494,6 +1494,18 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)))
|
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)))
|
||||||
|
|
||||||
|
strongSelf.listNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||||
|
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||||
|
itemHeaderNode.updateTheme(theme: presentationData.theme)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
strongSelf.recentListNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||||
|
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||||
|
itemHeaderNode.updateTheme(theme: presentationData.theme)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -210,7 +210,9 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese
|
|||||||
content = SystemVideoContent(url: embedUrl, imageReference: .webPage(webPage: WebpageReference(webpage), media: image), dimensions: webpageContent.embedSize?.cgSize ?? CGSize(width: 640.0, height: 640.0), duration: Int32(webpageContent.duration ?? 0))
|
content = SystemVideoContent(url: embedUrl, imageReference: .webPage(webPage: WebpageReference(webpage), media: image), dimensions: webpageContent.embedSize?.cgSize ?? CGSize(width: 640.0, height: 640.0), duration: Int32(webpageContent.duration ?? 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if content == nil, let webEmbedContent = WebEmbedVideoContent(webPage: webpage, webpageContent: webpageContent, forcedTimestamp: timecode.flatMap(Int.init)) {
|
if content == nil, let webEmbedContent = WebEmbedVideoContent(webPage: webpage, webpageContent: webpageContent, forcedTimestamp: timecode.flatMap(Int.init), openUrl: { url in
|
||||||
|
performAction(.url(url: url.absoluteString, concealed: false))
|
||||||
|
}) {
|
||||||
content = webEmbedContent
|
content = webEmbedContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,6 +493,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
var disablePictureInPicture = false
|
var disablePictureInPicture = false
|
||||||
var disablePlayerControls = false
|
var disablePlayerControls = false
|
||||||
var forceEnablePiP = false
|
var forceEnablePiP = false
|
||||||
|
var forceEnableUserInteraction = false
|
||||||
var isAnimated = false
|
var isAnimated = false
|
||||||
if let content = item.content as? NativeVideoContent {
|
if let content = item.content as? NativeVideoContent {
|
||||||
isAnimated = content.fileReference.media.isAnimated
|
isAnimated = content.fileReference.media.isAnimated
|
||||||
@ -503,6 +504,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
let type = webEmbedType(content: content.webpageContent)
|
let type = webEmbedType(content: content.webpageContent)
|
||||||
switch type {
|
switch type {
|
||||||
case .youtube:
|
case .youtube:
|
||||||
|
forceEnableUserInteraction = true
|
||||||
disablePictureInPicture = !(item.configuration?.youtubePictureInPictureEnabled ?? false)
|
disablePictureInPicture = !(item.configuration?.youtubePictureInPictureEnabled ?? false)
|
||||||
self.videoFramePreview = YoutubeEmbedFramePreview(context: item.context, content: content)
|
self.videoFramePreview = YoutubeEmbedFramePreview(context: item.context, content: content)
|
||||||
case .iframe:
|
case .iframe:
|
||||||
@ -527,7 +529,14 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
let mediaManager = item.context.sharedContext.mediaManager
|
let mediaManager = item.context.sharedContext.mediaManager
|
||||||
|
|
||||||
let videoNode = UniversalVideoNode(postbox: item.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: item.content, priority: .gallery)
|
let videoNode = UniversalVideoNode(postbox: item.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: item.content, priority: .gallery)
|
||||||
let videoSize = CGSize(width: item.content.dimensions.width * 2.0, height: item.content.dimensions.height * 2.0)
|
|
||||||
|
let videoScale: CGFloat
|
||||||
|
if item.content is WebEmbedVideoContent {
|
||||||
|
videoScale = 1.0
|
||||||
|
} else {
|
||||||
|
videoScale = 2.0
|
||||||
|
}
|
||||||
|
let videoSize = CGSize(width: item.content.dimensions.width * videoScale, height: item.content.dimensions.height * videoScale)
|
||||||
videoNode.updateLayout(size: videoSize, transition: .immediate)
|
videoNode.updateLayout(size: videoSize, transition: .immediate)
|
||||||
videoNode.ownsContentNodeUpdated = { [weak self] value in
|
videoNode.ownsContentNodeUpdated = { [weak self] value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -546,7 +555,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.videoNode = videoNode
|
self.videoNode = videoNode
|
||||||
videoNode.isUserInteractionEnabled = disablePlayerControls
|
videoNode.isUserInteractionEnabled = disablePlayerControls || forceEnableUserInteraction
|
||||||
videoNode.backgroundColor = videoNode.ownsContentNode ? UIColor.black : UIColor(rgb: 0x333335)
|
videoNode.backgroundColor = videoNode.ownsContentNode ? UIColor.black : UIColor(rgb: 0x333335)
|
||||||
if item.fromPlayingVideo {
|
if item.fromPlayingVideo {
|
||||||
videoNode.canAttachContent = false
|
videoNode.canAttachContent = false
|
||||||
|
@ -44,6 +44,15 @@ public class BaseLinesChartController: BaseChartController {
|
|||||||
self.setBackButtonVisibilityClosure?(isZoomed, animated)
|
self.setBackButtonVisibilityClosure?(isZoomed, animated)
|
||||||
|
|
||||||
updateChartRangeTitle(animated: animated)
|
updateChartRangeTitle(animated: animated)
|
||||||
|
|
||||||
|
let initial = initialChartsCollection
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
|
||||||
|
if let lastDate = initial.axisValues.last {
|
||||||
|
TimeInterval.animationDurationMultipler = 0.00001
|
||||||
|
self.didTapZoomIn(date: lastDate, pointIndex: initial.axisValues.count - 1)
|
||||||
|
TimeInterval.animationDurationMultipler = 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateChartRangeTitle(animated: Bool) {
|
func updateChartRangeTitle(animated: Bool) {
|
||||||
|
@ -137,7 +137,9 @@ public struct InstantPageGalleryEntry: Equatable {
|
|||||||
}))
|
}))
|
||||||
}), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in })
|
}), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in })
|
||||||
} else {
|
} else {
|
||||||
if let content = WebEmbedVideoContent(webPage: embedWebpage, webpageContent: webpageContent) {
|
if let content = WebEmbedVideoContent(webPage: embedWebpage, webpageContent: webpageContent, openUrl: { url in
|
||||||
|
|
||||||
|
}) {
|
||||||
return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: nil, indexData: nil, contentInfo: .webPage(webPage, embedWebpage, nil), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in })
|
return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: nil, indexData: nil, contentInfo: .webPage(webPage, embedWebpage, nil), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in })
|
||||||
} else {
|
} else {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
|
@ -39,7 +39,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
case overview(PresentationTheme, MessageStats, Int32?)
|
case overview(PresentationTheme, MessageStats, Int32?)
|
||||||
|
|
||||||
case interactionsTitle(PresentationTheme, String)
|
case interactionsTitle(PresentationTheme, String)
|
||||||
case interactionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType)
|
case interactionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, StatsGraph?, ChartType)
|
||||||
|
|
||||||
case publicForwardsTitle(PresentationTheme, String)
|
case publicForwardsTitle(PresentationTheme, String)
|
||||||
case publicForward(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Message)
|
case publicForward(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Message)
|
||||||
@ -92,8 +92,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .interactionsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
case let .interactionsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsDetailedGraph, lhsType):
|
||||||
if case let .interactionsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
if case let .interactionsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsDetailedGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsDetailedGraph == rhsDetailedGraph, lhsType == rhsType {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -126,13 +126,17 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||||
case let .overview(_, stats, publicShares):
|
case let .overview(_, stats, publicShares):
|
||||||
return MessageStatsOverviewItem(presentationData: presentationData, stats: stats, publicShares: publicShares, sectionId: self.section, style: .blocks)
|
return MessageStatsOverviewItem(presentationData: presentationData, stats: stats, publicShares: publicShares, sectionId: self.section, style: .blocks)
|
||||||
case let .interactionsGraph(_, _, _, graph, type):
|
case let .interactionsGraph(_, _, _, graph, detailedGraph, type):
|
||||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, getDetailsData: { date, completion in
|
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, getDetailsData: { date, completion in
|
||||||
let _ = arguments.loadDetailedGraph(graph, Int64(date.timeIntervalSince1970) * 1000).start(next: { graph in
|
if let detailedGraph = detailedGraph, case let .Loaded(_, data) = detailedGraph {
|
||||||
if let graph = graph, case let .Loaded(_, data) = graph {
|
completion(data)
|
||||||
completion(data)
|
} else {
|
||||||
}
|
let _ = arguments.loadDetailedGraph(graph, Int64(date.timeIntervalSince1970) * 1000).start(next: { graph in
|
||||||
})
|
if let graph = graph, case let .Loaded(_, data) = graph {
|
||||||
|
completion(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}, sectionId: self.section, style: .blocks)
|
}, sectionId: self.section, style: .blocks)
|
||||||
case let .publicForward(_, _, _, _, message):
|
case let .publicForward(_, _, _, _, message):
|
||||||
var views: Int = 0
|
var views: Int = 0
|
||||||
@ -148,9 +152,6 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", decimalSeparator: ",", groupingSeparator: ""), nameDisplayOrder: .firstLast, context: arguments.context, peer: message.peers[message.id.peerId]!, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: nil), revealOptions: nil, switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", decimalSeparator: ",", groupingSeparator: ""), nameDisplayOrder: .firstLast, context: arguments.context, peer: message.peers[message.id.peerId]!, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: nil), revealOptions: nil, switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||||
arguments.openMessage(message.id)
|
arguments.openMessage(message.id)
|
||||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: nil)
|
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: nil)
|
||||||
// return StatsMessageItem(context: arguments.context, presentationData: presentationData, message: message, views: 0, forwards: 0, sectionId: self.section, style: .blocks, action: {
|
|
||||||
// arguments.openMessage(message.id)
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +165,7 @@ private func messageStatsControllerEntries(data: MessageStats?, messages: Search
|
|||||||
|
|
||||||
if !data.interactionsGraph.isEmpty {
|
if !data.interactionsGraph.isEmpty {
|
||||||
entries.append(.interactionsTitle(presentationData.theme, presentationData.strings.Stats_MessageInteractionsTitle.uppercased()))
|
entries.append(.interactionsTitle(presentationData.theme, presentationData.strings.Stats_MessageInteractionsTitle.uppercased()))
|
||||||
entries.append(.interactionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.interactionsGraph, .twoAxisStep))
|
entries.append(.interactionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.interactionsGraph, data.detailedInteractionsGraph, .twoAxisStep))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let messages = messages, !messages.messages.isEmpty {
|
if let messages = messages, !messages.messages.isEmpty {
|
||||||
|
@ -9,11 +9,13 @@ public struct MessageStats: Equatable {
|
|||||||
public let views: Int
|
public let views: Int
|
||||||
public let forwards: Int
|
public let forwards: Int
|
||||||
public let interactionsGraph: StatsGraph
|
public let interactionsGraph: StatsGraph
|
||||||
|
public let detailedInteractionsGraph: StatsGraph?
|
||||||
|
|
||||||
init(views: Int, forwards: Int, interactionsGraph: StatsGraph) {
|
init(views: Int, forwards: Int, interactionsGraph: StatsGraph, detailedInteractionsGraph: StatsGraph?) {
|
||||||
self.views = views
|
self.views = views
|
||||||
self.forwards = forwards
|
self.forwards = forwards
|
||||||
self.interactionsGraph = interactionsGraph
|
self.interactionsGraph = interactionsGraph
|
||||||
|
self.detailedInteractionsGraph = detailedInteractionsGraph
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func == (lhs: MessageStats, rhs: MessageStats) -> Bool {
|
public static func == (lhs: MessageStats, rhs: MessageStats) -> Bool {
|
||||||
@ -26,11 +28,14 @@ public struct MessageStats: Equatable {
|
|||||||
if lhs.interactionsGraph != rhs.interactionsGraph {
|
if lhs.interactionsGraph != rhs.interactionsGraph {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.detailedInteractionsGraph != rhs.detailedInteractionsGraph {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedInteractionsGraph(_ interactionsGraph: StatsGraph) -> MessageStats {
|
public func withUpdatedInteractionsGraph(_ interactionsGraph: StatsGraph) -> MessageStats {
|
||||||
return MessageStats(views: self.views, forwards: self.forwards, interactionsGraph: self.interactionsGraph)
|
return MessageStats(views: self.views, forwards: self.forwards, interactionsGraph: interactionsGraph, detailedInteractionsGraph: self.detailedInteractionsGraph)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,8 +44,7 @@ public struct MessageStatsContextState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func requestMessageStats(postbox: Postbox, network: Network, datacenterId: Int32, messageId: MessageId, dark: Bool = false) -> Signal<MessageStats?, NoError> {
|
private func requestMessageStats(postbox: Postbox, network: Network, datacenterId: Int32, messageId: MessageId, dark: Bool = false) -> Signal<MessageStats?, NoError> {
|
||||||
return .single(nil)
|
return postbox.transaction { transaction -> (Peer, Message)? in
|
||||||
/*return postbox.transaction { transaction -> (Peer, Message)? in
|
|
||||||
if let peer = transaction.getPeer(messageId.peerId), let message = transaction.getMessage(messageId) {
|
if let peer = transaction.getPeer(messageId.peerId), let message = transaction.getMessage(messageId) {
|
||||||
return (peer, message)
|
return (peer, message)
|
||||||
} else {
|
} else {
|
||||||
@ -79,15 +83,25 @@ private func requestMessageStats(postbox: Postbox, network: Network, datacenterI
|
|||||||
}
|
}
|
||||||
|
|
||||||
return signal
|
return signal
|
||||||
|> map { result -> MessageStats? in
|
|> mapToSignal { result -> Signal<MessageStats?, MTRpcError> in
|
||||||
if case let .messageStats(apiViewsGraph) = result {
|
if case let .messageStats(apiViewsGraph) = result {
|
||||||
return MessageStats(views: views, forwards: forwards, interactionsGraph: StatsGraph(apiStatsGraph: apiViewsGraph))
|
let interactionsGraph = StatsGraph(apiStatsGraph: apiViewsGraph)
|
||||||
|
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||||
|
if case let .Loaded(tokenValue, _) = interactionsGraph, let token = tokenValue, Int64(message.timestamp + 60 * 60 * 24 * 2) > Int64(timestamp) {
|
||||||
|
return requestGraph(network: network, datacenterId: datacenterId, token: token, x: 1601596800000)
|
||||||
|
|> castError(MTRpcError.self)
|
||||||
|
|> map { detailedGraph -> MessageStats? in
|
||||||
|
return MessageStats(views: views, forwards: forwards, interactionsGraph: interactionsGraph, detailedInteractionsGraph: detailedGraph)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .single(MessageStats(views: views, forwards: forwards, interactionsGraph: interactionsGraph, detailedInteractionsGraph: nil))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return .single(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class MessageStatsContextImpl {
|
private final class MessageStatsContextImpl {
|
||||||
|
@ -345,15 +345,32 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
|||||||
|> mapToSignal { result, additionalResult -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> in
|
|> mapToSignal { result, additionalResult -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> in
|
||||||
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
||||||
var additional: SearchMessagesPeerState? = mergedState(transaction: transaction, state: state?.additional, result: additionalResult)
|
var additional: SearchMessagesPeerState? = mergedState(transaction: transaction, state: state?.additional, result: additionalResult)
|
||||||
if state?.additional == nil, case let .general(tags, _, _) = location {
|
|
||||||
let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: tags)
|
if state?.additional == nil {
|
||||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
switch location {
|
||||||
for message in secretMessages {
|
case let .general(tags, minDate, maxDate), let .group(_, tags, minDate, maxDate):
|
||||||
if let readState = transaction.getCombinedPeerReadState(message.id.peerId) {
|
let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: tags)
|
||||||
readStates[message.id.peerId] = readState
|
var filteredMessages: [Message] = []
|
||||||
}
|
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||||
|
for message in secretMessages {
|
||||||
|
var match = true
|
||||||
|
if let minDate = minDate, message.timestamp < minDate {
|
||||||
|
match = false
|
||||||
|
}
|
||||||
|
if let maxDate = maxDate, message.timestamp > maxDate {
|
||||||
|
match = false
|
||||||
|
}
|
||||||
|
if match {
|
||||||
|
filteredMessages.append(message)
|
||||||
|
if let readState = transaction.getCombinedPeerReadState(message.id.peerId) {
|
||||||
|
readStates[message.id.peerId] = readState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
additional = SearchMessagesPeerState(messages: filteredMessages, readStates: readStates, totalCount: Int32(filteredMessages.count), completed: true, nextRate: nil)
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
additional = SearchMessagesPeerState(messages: secretMessages, readStates: readStates, totalCount: Int32(secretMessages.count), completed: true, nextRate: nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let updatedState = SearchMessagesState(main: mergedState(transaction: transaction, state: state?.main, result: result) ?? SearchMessagesPeerState(messages: [], readStates: [:], totalCount: 0, completed: true, nextRate: nil), additional: additional)
|
let updatedState = SearchMessagesState(main: mergedState(transaction: transaction, state: state?.main, result: result) ?? SearchMessagesPeerState(messages: [], readStates: [:], totalCount: 0, completed: true, nextRate: nil), additional: additional)
|
||||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||||||
|
|
||||||
public class Serialization: NSObject, MTSerialization {
|
public class Serialization: NSObject, MTSerialization {
|
||||||
public func currentLayer() -> UInt {
|
public func currentLayer() -> UInt {
|
||||||
return 119
|
return 120
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseMessage(_ data: Data!) -> Any! {
|
public func parseMessage(_ data: Data!) -> Any! {
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -38,7 +38,7 @@
|
|||||||
function getCurrentTime() {
|
function getCurrentTime() {
|
||||||
downloadProgress = player.getVideoLoadedFraction();
|
downloadProgress = player.getVideoLoadedFraction();
|
||||||
position = player.getCurrentTime();
|
position = player.getCurrentTime();
|
||||||
storyboardSpec = player.getStoryboardFormat();
|
//storyboardSpec = player.getStoryboardFormat();
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
invoke("tick");
|
invoke("tick");
|
||||||
@ -67,6 +67,7 @@
|
|||||||
function onReady(event) {
|
function onReady(event) {
|
||||||
window.location.href = "embed://onReady?data=" + event.data;
|
window.location.href = "embed://onReady?data=" + event.data;
|
||||||
iframe = document.getElementById("player");
|
iframe = document.getElementById("player");
|
||||||
|
iframe.referrerPolicy = "origin";
|
||||||
duration = player.getDuration();
|
duration = player.getDuration();
|
||||||
invoke("tick");
|
invoke("tick");
|
||||||
}
|
}
|
||||||
|
@ -16,56 +16,56 @@ function initialize() {
|
|||||||
function tick() {
|
function tick() {
|
||||||
var watermark = document.getElementsByClassName("ytp-watermark")[0];
|
var watermark = document.getElementsByClassName("ytp-watermark")[0];
|
||||||
if (watermark != null) {
|
if (watermark != null) {
|
||||||
watermark.style.display = "none";
|
// watermark.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
var button = document.getElementsByClassName("ytp-large-play-button")[0];
|
var button = document.getElementsByClassName("ytp-large-play-button")[0];
|
||||||
if (button != null) {
|
if (button != null) {
|
||||||
button.style.display = "none";
|
// button.style.display = "none";
|
||||||
button.style.opacity = "0";
|
// button.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var progress = document.getElementsByClassName("ytp-spinner-container")[0];
|
var progress = document.getElementsByClassName("ytp-spinner-container")[0];
|
||||||
if (progress != null) {
|
if (progress != null) {
|
||||||
progress.style.display = "none";
|
// progress.style.display = "none";
|
||||||
progress.style.opacity = "0";
|
// progress.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var pause = document.getElementsByClassName("ytp-pause-overlay")[0];
|
var pause = document.getElementsByClassName("ytp-pause-overlay")[0];
|
||||||
if (pause != null) {
|
if (pause != null) {
|
||||||
pause.style.display = "none";
|
// pause.style.display = "none";
|
||||||
pause.style.opacity = "0";
|
// pause.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var chrome = document.getElementsByClassName("ytp-chrome-top")[0];
|
var chrome = document.getElementsByClassName("ytp-chrome-top")[0];
|
||||||
if (chrome != null) {
|
if (chrome != null) {
|
||||||
chrome.style.display = "none";
|
// chrome.style.display = "none";
|
||||||
chrome.style.opacity = "0";
|
// chrome.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var paid = document.getElementsByClassName("ytp-paid-content-overlay")[0];
|
var paid = document.getElementsByClassName("ytp-paid-content-overlay")[0];
|
||||||
if (paid != null) {
|
if (paid != null) {
|
||||||
paid.style.display = "none";
|
// paid.style.display = "none";
|
||||||
paid.style.opacity = "0";
|
// paid.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var gradient = document.getElementsByClassName("ytp-gradient-top")[0];
|
var gradient = document.getElementsByClassName("ytp-gradient-top")[0];
|
||||||
if (gradient != null) {
|
if (gradient != null) {
|
||||||
gradient.style.display = "none";
|
// gradient.style.display = "none";
|
||||||
gradient.style.opacity = "0";
|
// gradient.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var end = document.getElementsByClassName("html5-endscreen")[0];
|
var end = document.getElementsByClassName("html5-endscreen")[0];
|
||||||
if (end != null) {
|
if (end != null) {
|
||||||
end.style.display = "none";
|
// end.style.display = "none";
|
||||||
end.style.opacity = "0";
|
// end.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var elements = document.getElementsByClassName("ytp-ce-element");
|
var elements = document.getElementsByClassName("ytp-ce-element");
|
||||||
for (var i = 0; i < elements.length; i++) {
|
for (var i = 0; i < elements.length; i++) {
|
||||||
var element = elements[i]
|
var element = elements[i]
|
||||||
element.style.display = "none";
|
// element.style.display = "none";
|
||||||
element.style.opacity = "0";
|
// element.style.opacity = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
var video = document.getElementsByTagName("video")[0];
|
var video = document.getElementsByTagName("video")[0];
|
||||||
|
@ -2219,6 +2219,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, openMessageStats: { [weak self] id in
|
||||||
|
let _ = (context.account.postbox.transaction { transaction -> CachedPeerData? in
|
||||||
|
return transaction.getPeerCachedData(peerId: id.peerId)
|
||||||
|
} |> deliverOnMainQueue).start(next: { [weak self] cachedPeerData in
|
||||||
|
guard let strongSelf = self, let cachedPeerData = cachedPeerData else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.push(messageStatsController(context: context, messageId: id, cachedPeerData: cachedPeerData))
|
||||||
|
})
|
||||||
}, requestMessageUpdate: { [weak self] id in
|
}, requestMessageUpdate: { [weak self] id in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||||
|
@ -114,6 +114,7 @@ public final class ChatControllerInteraction {
|
|||||||
let openPeerContextMenu: (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void
|
let openPeerContextMenu: (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void
|
||||||
let openMessageReplies: (MessageId, Bool, Bool) -> Void
|
let openMessageReplies: (MessageId, Bool, Bool) -> Void
|
||||||
let openReplyThreadOriginalMessage: (Message) -> Void
|
let openReplyThreadOriginalMessage: (Message) -> Void
|
||||||
|
let openMessageStats: (MessageId) -> Void
|
||||||
|
|
||||||
let requestMessageUpdate: (MessageId) -> Void
|
let requestMessageUpdate: (MessageId) -> Void
|
||||||
let cancelInteractiveKeyboardGestures: () -> Void
|
let cancelInteractiveKeyboardGestures: () -> Void
|
||||||
@ -199,6 +200,7 @@ public final class ChatControllerInteraction {
|
|||||||
openPeerContextMenu: @escaping (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void,
|
openPeerContextMenu: @escaping (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void,
|
||||||
openMessageReplies: @escaping (MessageId, Bool, Bool) -> Void,
|
openMessageReplies: @escaping (MessageId, Bool, Bool) -> Void,
|
||||||
openReplyThreadOriginalMessage: @escaping (Message) -> Void,
|
openReplyThreadOriginalMessage: @escaping (Message) -> Void,
|
||||||
|
openMessageStats: @escaping (MessageId) -> Void,
|
||||||
requestMessageUpdate: @escaping (MessageId) -> Void,
|
requestMessageUpdate: @escaping (MessageId) -> Void,
|
||||||
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
||||||
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
|
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
|
||||||
@ -271,6 +273,7 @@ public final class ChatControllerInteraction {
|
|||||||
self.openPeerContextMenu = openPeerContextMenu
|
self.openPeerContextMenu = openPeerContextMenu
|
||||||
self.openMessageReplies = openMessageReplies
|
self.openMessageReplies = openMessageReplies
|
||||||
self.openReplyThreadOriginalMessage = openReplyThreadOriginalMessage
|
self.openReplyThreadOriginalMessage = openReplyThreadOriginalMessage
|
||||||
|
self.openMessageStats = openMessageStats
|
||||||
|
|
||||||
self.requestMessageUpdate = requestMessageUpdate
|
self.requestMessageUpdate = requestMessageUpdate
|
||||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||||
@ -321,6 +324,7 @@ public final class ChatControllerInteraction {
|
|||||||
}, openPeerContextMenu: { _, _, _, _ in
|
}, openPeerContextMenu: { _, _, _, _ in
|
||||||
}, openMessageReplies: { _, _, _ in
|
}, openMessageReplies: { _, _, _ in
|
||||||
}, openReplyThreadOriginalMessage: { _ in
|
}, openReplyThreadOriginalMessage: { _ in
|
||||||
|
}, openMessageStats: { _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
|
@ -605,7 +605,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
|||||||
})
|
})
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.canEdit {
|
if data.canEdit {
|
||||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_MessageDialogEdit, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_MessageDialogEdit, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor)
|
||||||
@ -808,9 +808,26 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
|||||||
}
|
}
|
||||||
|
|
||||||
var clearCacheAsDelete = false
|
var clearCacheAsDelete = false
|
||||||
if let _ = message.peers[message.id.peerId] as? TelegramChannel {
|
if message.id.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
var views: Int = 0
|
||||||
|
for attribute in message.attributes {
|
||||||
|
if let attribute = attribute as? ViewCountMessageAttribute {
|
||||||
|
views = attribute.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if views >= 100 {
|
||||||
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextViewStats, icon: { theme in
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Statistics"), color: theme.actionSheet.primaryTextColor)
|
||||||
|
}, action: { c, _ in
|
||||||
|
c.dismiss(completion: {
|
||||||
|
controllerInteraction.openMessageStats(messages[0].id)
|
||||||
|
})
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
clearCacheAsDelete = true
|
clearCacheAsDelete = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isReplyThreadHead, (!data.messageActions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty || clearCacheAsDelete) && !isAction {
|
if !isReplyThreadHead, (!data.messageActions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty || clearCacheAsDelete) && !isAction {
|
||||||
let title: String
|
let title: String
|
||||||
var isSending = false
|
var isSending = false
|
||||||
|
@ -453,6 +453,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, openPeerContextMenu: { _, _, _, _ in
|
}, openPeerContextMenu: { _, _, _, _ in
|
||||||
}, openMessageReplies: { _, _, _ in
|
}, openMessageReplies: { _, _, _ in
|
||||||
}, openReplyThreadOriginalMessage: { _ in
|
}, openReplyThreadOriginalMessage: { _ in
|
||||||
|
}, openMessageStats: { _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||||
|
@ -146,6 +146,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
|
|||||||
}, openPeerContextMenu: { _, _, _, _ in
|
}, openPeerContextMenu: { _, _, _, _ in
|
||||||
}, openMessageReplies: { _, _, _ in
|
}, openMessageReplies: { _, _, _ in
|
||||||
}, openReplyThreadOriginalMessage: { _ in
|
}, openReplyThreadOriginalMessage: { _ in
|
||||||
|
}, openMessageStats: { _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
|
@ -136,6 +136,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, openPeerContextMenu: { _, _, _, _ in
|
}, openPeerContextMenu: { _, _, _, _ in
|
||||||
}, openMessageReplies: { _, _, _ in
|
}, openMessageReplies: { _, _, _ in
|
||||||
}, openReplyThreadOriginalMessage: { _ in
|
}, openReplyThreadOriginalMessage: { _ in
|
||||||
|
}, openMessageStats: { _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||||
|
@ -1961,6 +1961,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}, openPeerContextMenu: { _, _, _, _ in
|
}, openPeerContextMenu: { _, _, _, _ in
|
||||||
}, openMessageReplies: { _, _, _ in
|
}, openMessageReplies: { _, _, _ in
|
||||||
}, openReplyThreadOriginalMessage: { _ in
|
}, openReplyThreadOriginalMessage: { _ in
|
||||||
|
}, openMessageStats: { _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
|
@ -1200,6 +1200,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, openPeerContextMenu: { _, _, _, _ in
|
}, openPeerContextMenu: { _, _, _, _ in
|
||||||
}, openMessageReplies: { _, _, _ in
|
}, openMessageReplies: { _, _, _ in
|
||||||
}, openReplyThreadOriginalMessage: { _ in
|
}, openReplyThreadOriginalMessage: { _ in
|
||||||
|
}, openMessageStats: { _ in
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
|
@ -75,18 +75,24 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
|||||||
|
|
||||||
let impl: WebEmbedImplementation
|
let impl: WebEmbedImplementation
|
||||||
|
|
||||||
|
private let openUrl: (URL) -> Void
|
||||||
private let intrinsicDimensions: CGSize
|
private let intrinsicDimensions: CGSize
|
||||||
private let webView: WKWebView
|
private let webView: WKWebView
|
||||||
|
|
||||||
private let semaphore = DispatchSemaphore(value: 0)
|
private let semaphore = DispatchSemaphore(value: 0)
|
||||||
private let queue = Queue()
|
private let queue = Queue()
|
||||||
|
|
||||||
init(impl: WebEmbedImplementation, intrinsicDimensions: CGSize) {
|
init(impl: WebEmbedImplementation, intrinsicDimensions: CGSize, openUrl: @escaping (URL) -> Void) {
|
||||||
self.impl = impl
|
self.impl = impl
|
||||||
self.intrinsicDimensions = intrinsicDimensions
|
self.intrinsicDimensions = intrinsicDimensions
|
||||||
|
self.openUrl = openUrl
|
||||||
|
|
||||||
let userContentController = WKUserContentController()
|
let userContentController = WKUserContentController()
|
||||||
userContentController.addUserScript(WKUserScript(source: "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta)", injectionTime: .atDocumentEnd, forMainFrameOnly: true))
|
if impl is YoutubeEmbedImplementation {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
userContentController.addUserScript(WKUserScript(source: "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta)", injectionTime: .atDocumentEnd, forMainFrameOnly: true))
|
||||||
|
}
|
||||||
|
|
||||||
let configuration = WKWebViewConfiguration()
|
let configuration = WKWebViewConfiguration()
|
||||||
configuration.allowsInlineMediaPlayback = true
|
configuration.allowsInlineMediaPlayback = true
|
||||||
@ -112,6 +118,8 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
|||||||
|
|
||||||
self.webView.navigationDelegate = self
|
self.webView.navigationDelegate = self
|
||||||
self.webView.scrollView.isScrollEnabled = false
|
self.webView.scrollView.isScrollEnabled = false
|
||||||
|
self.webView.allowsLinkPreview = false
|
||||||
|
self.webView.allowsBackForwardNavigationGestures = false
|
||||||
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
||||||
self.webView.accessibilityIgnoresInvertColors = true
|
self.webView.accessibilityIgnoresInvertColors = true
|
||||||
self.webView.scrollView.contentInsetAdjustmentBehavior = .never
|
self.webView.scrollView.contentInsetAdjustmentBehavior = .never
|
||||||
@ -159,19 +167,19 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
||||||
|
print("w")
|
||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||||
self.impl.pageReady()
|
self.impl.pageReady()
|
||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
||||||
if let error = error as? WKError, error.code.rawValue == 204 {
|
if let error = error as? WKError, error.code.rawValue == 204 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
||||||
if let url = navigationAction.request.url, url.scheme == "embed" {
|
if let url = navigationAction.request.url, url.scheme == "embed" {
|
||||||
self.impl.callback(url: url)
|
self.impl.callback(url: url)
|
||||||
@ -179,6 +187,9 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
|||||||
} else if let _ = navigationAction.targetFrame {
|
} else if let _ = navigationAction.targetFrame {
|
||||||
decisionHandler(.allow)
|
decisionHandler(.allow)
|
||||||
} else {
|
} else {
|
||||||
|
if let url = navigationAction.request.url, url.absoluteString.contains("youtube") {
|
||||||
|
self.openUrl(url)
|
||||||
|
}
|
||||||
decisionHandler(.cancel)
|
decisionHandler(.cancel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,9 @@ public final class WebEmbedVideoContent: UniversalVideoContent {
|
|||||||
public let dimensions: CGSize
|
public let dimensions: CGSize
|
||||||
public let duration: Int32
|
public let duration: Int32
|
||||||
let forcedTimestamp: Int?
|
let forcedTimestamp: Int?
|
||||||
|
let openUrl: (URL) -> Void
|
||||||
|
|
||||||
public init?(webPage: TelegramMediaWebpage, webpageContent: TelegramMediaWebpageLoadedContent, forcedTimestamp: Int? = nil) {
|
public init?(webPage: TelegramMediaWebpage, webpageContent: TelegramMediaWebpageLoadedContent, forcedTimestamp: Int? = nil, openUrl: @escaping (URL) -> Void) {
|
||||||
guard let embedUrl = webpageContent.embedUrl else {
|
guard let embedUrl = webpageContent.embedUrl else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -30,10 +31,11 @@ public final class WebEmbedVideoContent: UniversalVideoContent {
|
|||||||
self.dimensions = webpageContent.embedSize?.cgSize ?? CGSize(width: 128.0, height: 128.0)
|
self.dimensions = webpageContent.embedSize?.cgSize ?? CGSize(width: 128.0, height: 128.0)
|
||||||
self.duration = Int32(webpageContent.duration ?? (0 as Int))
|
self.duration = Int32(webpageContent.duration ?? (0 as Int))
|
||||||
self.forcedTimestamp = forcedTimestamp
|
self.forcedTimestamp = forcedTimestamp
|
||||||
|
self.openUrl = openUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeContentNode(postbox: Postbox, audioSession: ManagedAudioSession) -> UniversalVideoContentNode & ASDisplayNode {
|
public func makeContentNode(postbox: Postbox, audioSession: ManagedAudioSession) -> UniversalVideoContentNode & ASDisplayNode {
|
||||||
return WebEmbedVideoContentNode(postbox: postbox, audioSessionManager: audioSession, webPage: self.webPage, webpageContent: self.webpageContent, forcedTimestamp: self.forcedTimestamp)
|
return WebEmbedVideoContentNode(postbox: postbox, audioSessionManager: audioSession, webPage: self.webPage, webpageContent: self.webpageContent, forcedTimestamp: self.forcedTimestamp, openUrl: self.openUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ final class WebEmbedVideoContentNode: ASDisplayNode, UniversalVideoContentNode {
|
|||||||
|
|
||||||
private var readyDisposable = MetaDisposable()
|
private var readyDisposable = MetaDisposable()
|
||||||
|
|
||||||
init(postbox: Postbox, audioSessionManager: ManagedAudioSession, webPage: TelegramMediaWebpage, webpageContent: TelegramMediaWebpageLoadedContent, forcedTimestamp: Int? = nil) {
|
init(postbox: Postbox, audioSessionManager: ManagedAudioSession, webPage: TelegramMediaWebpage, webpageContent: TelegramMediaWebpageLoadedContent, forcedTimestamp: Int? = nil, openUrl: @escaping (URL) -> Void) {
|
||||||
self.webpageContent = webpageContent
|
self.webpageContent = webpageContent
|
||||||
|
|
||||||
if let embedSize = webpageContent.embedSize {
|
if let embedSize = webpageContent.embedSize {
|
||||||
@ -83,7 +85,7 @@ final class WebEmbedVideoContentNode: ASDisplayNode, UniversalVideoContentNode {
|
|||||||
|
|
||||||
let embedType = webEmbedType(content: webpageContent, forcedTimestamp: forcedTimestamp)
|
let embedType = webEmbedType(content: webpageContent, forcedTimestamp: forcedTimestamp)
|
||||||
let embedImpl = webEmbedImplementation(for: embedType)
|
let embedImpl = webEmbedImplementation(for: embedType)
|
||||||
self.playerNode = WebEmbedPlayerNode(impl: embedImpl, intrinsicDimensions: self.intrinsicDimensions)
|
self.playerNode = WebEmbedPlayerNode(impl: embedImpl, intrinsicDimensions: self.intrinsicDimensions, openUrl: openUrl)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
@ -174,8 +174,8 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation {
|
|||||||
updateStatus(self.status)
|
updateStatus(self.status)
|
||||||
|
|
||||||
let html = String(format: htmlTemplate, paramsJson)
|
let html = String(format: htmlTemplate, paramsJson)
|
||||||
webView.loadHTMLString(html, baseURL: URL(string: "https://youtube.com/"))
|
webView.loadHTMLString(html, baseURL: URL(string: "https://messenger.telegram.org"))
|
||||||
webView.isUserInteractionEnabled = false
|
// webView.isUserInteractionEnabled = false
|
||||||
|
|
||||||
userContentController.addUserScript(WKUserScript(source: userScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false))
|
userContentController.addUserScript(WKUserScript(source: userScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user