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.";
|
||||
|
||||
"ChannelInfo.Stats" = "Statistics";
|
||||
"ChannelInfo.Stats" = "View Statistics";
|
||||
|
||||
"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.";
|
||||
|
||||
"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 {
|
||||
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.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))
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -493,6 +493,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var disablePictureInPicture = false
|
||||
var disablePlayerControls = false
|
||||
var forceEnablePiP = false
|
||||
var forceEnableUserInteraction = false
|
||||
var isAnimated = false
|
||||
if let content = item.content as? NativeVideoContent {
|
||||
isAnimated = content.fileReference.media.isAnimated
|
||||
@ -503,6 +504,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
let type = webEmbedType(content: content.webpageContent)
|
||||
switch type {
|
||||
case .youtube:
|
||||
forceEnableUserInteraction = true
|
||||
disablePictureInPicture = !(item.configuration?.youtubePictureInPictureEnabled ?? false)
|
||||
self.videoFramePreview = YoutubeEmbedFramePreview(context: item.context, content: content)
|
||||
case .iframe:
|
||||
@ -527,7 +529,14 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
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 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.ownsContentNodeUpdated = { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
@ -546,7 +555,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
}
|
||||
}
|
||||
self.videoNode = videoNode
|
||||
videoNode.isUserInteractionEnabled = disablePlayerControls
|
||||
videoNode.isUserInteractionEnabled = disablePlayerControls || forceEnableUserInteraction
|
||||
videoNode.backgroundColor = videoNode.ownsContentNode ? UIColor.black : UIColor(rgb: 0x333335)
|
||||
if item.fromPlayingVideo {
|
||||
videoNode.canAttachContent = false
|
||||
|
@ -44,6 +44,15 @@ public class BaseLinesChartController: BaseChartController {
|
||||
self.setBackButtonVisibilityClosure?(isZoomed, 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) {
|
||||
|
@ -137,7 +137,9 @@ public struct InstantPageGalleryEntry: Equatable {
|
||||
}))
|
||||
}), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in })
|
||||
} 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 })
|
||||
} else {
|
||||
preconditionFailure()
|
||||
|
@ -39,7 +39,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
case overview(PresentationTheme, MessageStats, Int32?)
|
||||
|
||||
case interactionsTitle(PresentationTheme, String)
|
||||
case interactionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType)
|
||||
case interactionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, StatsGraph?, ChartType)
|
||||
|
||||
case publicForwardsTitle(PresentationTheme, String)
|
||||
case publicForward(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Message)
|
||||
@ -92,8 +92,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .interactionsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .interactionsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
case let .interactionsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsDetailedGraph, lhsType):
|
||||
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
|
||||
} else {
|
||||
return false
|
||||
@ -126,13 +126,17 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .overview(_, stats, publicShares):
|
||||
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
|
||||
let _ = arguments.loadDetailedGraph(graph, Int64(date.timeIntervalSince1970) * 1000).start(next: { graph in
|
||||
if let graph = graph, case let .Loaded(_, data) = graph {
|
||||
completion(data)
|
||||
}
|
||||
})
|
||||
if let detailedGraph = detailedGraph, case let .Loaded(_, data) = detailedGraph {
|
||||
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)
|
||||
case let .publicForward(_, _, _, _, message):
|
||||
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: {
|
||||
arguments.openMessage(message.id)
|
||||
}, 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 {
|
||||
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 {
|
||||
|
@ -9,11 +9,13 @@ public struct MessageStats: Equatable {
|
||||
public let views: Int
|
||||
public let forwards: Int
|
||||
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.forwards = forwards
|
||||
self.interactionsGraph = interactionsGraph
|
||||
self.detailedInteractionsGraph = detailedInteractionsGraph
|
||||
}
|
||||
|
||||
public static func == (lhs: MessageStats, rhs: MessageStats) -> Bool {
|
||||
@ -26,11 +28,14 @@ public struct MessageStats: Equatable {
|
||||
if lhs.interactionsGraph != rhs.interactionsGraph {
|
||||
return false
|
||||
}
|
||||
if lhs.detailedInteractionsGraph != rhs.detailedInteractionsGraph {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
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> {
|
||||
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) {
|
||||
return (peer, message)
|
||||
} else {
|
||||
@ -79,15 +83,25 @@ private func requestMessageStats(postbox: Postbox, network: Network, datacenterI
|
||||
}
|
||||
|
||||
return signal
|
||||
|> map { result -> MessageStats? in
|
||||
|> mapToSignal { result -> Signal<MessageStats?, MTRpcError> in
|
||||
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 {
|
||||
return nil
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|> retryRequest
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private final class MessageStatsContextImpl {
|
||||
|
@ -345,15 +345,32 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
||||
|> mapToSignal { result, additionalResult -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> in
|
||||
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
||||
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)
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
for message in secretMessages {
|
||||
if let readState = transaction.getCombinedPeerReadState(message.id.peerId) {
|
||||
readStates[message.id.peerId] = readState
|
||||
}
|
||||
|
||||
if state?.additional == nil {
|
||||
switch location {
|
||||
case let .general(tags, minDate, maxDate), let .group(_, tags, minDate, maxDate):
|
||||
let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: tags)
|
||||
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)
|
||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 119
|
||||
return 120
|
||||
}
|
||||
|
||||
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() {
|
||||
downloadProgress = player.getVideoLoadedFraction();
|
||||
position = player.getCurrentTime();
|
||||
storyboardSpec = player.getStoryboardFormat();
|
||||
//storyboardSpec = player.getStoryboardFormat();
|
||||
|
||||
updateState();
|
||||
invoke("tick");
|
||||
@ -67,6 +67,7 @@
|
||||
function onReady(event) {
|
||||
window.location.href = "embed://onReady?data=" + event.data;
|
||||
iframe = document.getElementById("player");
|
||||
iframe.referrerPolicy = "origin";
|
||||
duration = player.getDuration();
|
||||
invoke("tick");
|
||||
}
|
||||
|
@ -16,56 +16,56 @@ function initialize() {
|
||||
function tick() {
|
||||
var watermark = document.getElementsByClassName("ytp-watermark")[0];
|
||||
if (watermark != null) {
|
||||
watermark.style.display = "none";
|
||||
// watermark.style.display = "none";
|
||||
}
|
||||
|
||||
var button = document.getElementsByClassName("ytp-large-play-button")[0];
|
||||
if (button != null) {
|
||||
button.style.display = "none";
|
||||
button.style.opacity = "0";
|
||||
// button.style.display = "none";
|
||||
// button.style.opacity = "0";
|
||||
}
|
||||
|
||||
var progress = document.getElementsByClassName("ytp-spinner-container")[0];
|
||||
if (progress != null) {
|
||||
progress.style.display = "none";
|
||||
progress.style.opacity = "0";
|
||||
// progress.style.display = "none";
|
||||
// progress.style.opacity = "0";
|
||||
}
|
||||
|
||||
var pause = document.getElementsByClassName("ytp-pause-overlay")[0];
|
||||
if (pause != null) {
|
||||
pause.style.display = "none";
|
||||
pause.style.opacity = "0";
|
||||
// pause.style.display = "none";
|
||||
// pause.style.opacity = "0";
|
||||
}
|
||||
|
||||
var chrome = document.getElementsByClassName("ytp-chrome-top")[0];
|
||||
if (chrome != null) {
|
||||
chrome.style.display = "none";
|
||||
chrome.style.opacity = "0";
|
||||
// chrome.style.display = "none";
|
||||
// chrome.style.opacity = "0";
|
||||
}
|
||||
|
||||
var paid = document.getElementsByClassName("ytp-paid-content-overlay")[0];
|
||||
if (paid != null) {
|
||||
paid.style.display = "none";
|
||||
paid.style.opacity = "0";
|
||||
// paid.style.display = "none";
|
||||
// paid.style.opacity = "0";
|
||||
}
|
||||
|
||||
var gradient = document.getElementsByClassName("ytp-gradient-top")[0];
|
||||
if (gradient != null) {
|
||||
gradient.style.display = "none";
|
||||
gradient.style.opacity = "0";
|
||||
// gradient.style.display = "none";
|
||||
// gradient.style.opacity = "0";
|
||||
}
|
||||
|
||||
var end = document.getElementsByClassName("html5-endscreen")[0];
|
||||
if (end != null) {
|
||||
end.style.display = "none";
|
||||
end.style.opacity = "0";
|
||||
// end.style.display = "none";
|
||||
// end.style.opacity = "0";
|
||||
}
|
||||
|
||||
var elements = document.getElementsByClassName("ytp-ce-element");
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
var element = elements[i]
|
||||
element.style.display = "none";
|
||||
element.style.opacity = "0";
|
||||
// element.style.display = "none";
|
||||
// element.style.opacity = "0";
|
||||
}
|
||||
|
||||
var video = document.getElementsByTagName("video")[0];
|
||||
|
@ -2219,6 +2219,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
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
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||
|
@ -114,6 +114,7 @@ public final class ChatControllerInteraction {
|
||||
let openPeerContextMenu: (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void
|
||||
let openMessageReplies: (MessageId, Bool, Bool) -> Void
|
||||
let openReplyThreadOriginalMessage: (Message) -> Void
|
||||
let openMessageStats: (MessageId) -> Void
|
||||
|
||||
let requestMessageUpdate: (MessageId) -> Void
|
||||
let cancelInteractiveKeyboardGestures: () -> Void
|
||||
@ -199,6 +200,7 @@ public final class ChatControllerInteraction {
|
||||
openPeerContextMenu: @escaping (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void,
|
||||
openMessageReplies: @escaping (MessageId, Bool, Bool) -> Void,
|
||||
openReplyThreadOriginalMessage: @escaping (Message) -> Void,
|
||||
openMessageStats: @escaping (MessageId) -> Void,
|
||||
requestMessageUpdate: @escaping (MessageId) -> Void,
|
||||
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
||||
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
|
||||
@ -271,6 +273,7 @@ public final class ChatControllerInteraction {
|
||||
self.openPeerContextMenu = openPeerContextMenu
|
||||
self.openMessageReplies = openMessageReplies
|
||||
self.openReplyThreadOriginalMessage = openReplyThreadOriginalMessage
|
||||
self.openMessageStats = openMessageStats
|
||||
|
||||
self.requestMessageUpdate = requestMessageUpdate
|
||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||
@ -321,6 +324,7 @@ public final class ChatControllerInteraction {
|
||||
}, openPeerContextMenu: { _, _, _, _ in
|
||||
}, openMessageReplies: { _, _, _ in
|
||||
}, openReplyThreadOriginalMessage: { _ in
|
||||
}, openMessageStats: { _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -808,9 +808,26 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if !isReplyThreadHead, (!data.messageActions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty || clearCacheAsDelete) && !isAction {
|
||||
let title: String
|
||||
var isSending = false
|
||||
|
@ -453,6 +453,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
}, openPeerContextMenu: { _, _, _, _ in
|
||||
}, openMessageReplies: { _, _, _ in
|
||||
}, openReplyThreadOriginalMessage: { _ in
|
||||
}, openMessageStats: { _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||
|
@ -146,6 +146,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
|
||||
}, openPeerContextMenu: { _, _, _, _ in
|
||||
}, openMessageReplies: { _, _, _ in
|
||||
}, openReplyThreadOriginalMessage: { _ in
|
||||
}, openMessageStats: { _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -136,6 +136,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
||||
}, openPeerContextMenu: { _, _, _, _ in
|
||||
}, openMessageReplies: { _, _, _ in
|
||||
}, openReplyThreadOriginalMessage: { _ in
|
||||
}, openMessageStats: { _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||
|
@ -1961,6 +1961,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}, openPeerContextMenu: { _, _, _, _ in
|
||||
}, openMessageReplies: { _, _, _ in
|
||||
}, openReplyThreadOriginalMessage: { _ in
|
||||
}, openMessageStats: { _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -1200,6 +1200,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
}, openPeerContextMenu: { _, _, _, _ in
|
||||
}, openMessageReplies: { _, _, _ in
|
||||
}, openReplyThreadOriginalMessage: { _ in
|
||||
}, openMessageStats: { _ in
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -75,18 +75,24 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
||||
|
||||
let impl: WebEmbedImplementation
|
||||
|
||||
private let openUrl: (URL) -> Void
|
||||
private let intrinsicDimensions: CGSize
|
||||
private let webView: WKWebView
|
||||
|
||||
private let semaphore = DispatchSemaphore(value: 0)
|
||||
private let queue = Queue()
|
||||
|
||||
init(impl: WebEmbedImplementation, intrinsicDimensions: CGSize) {
|
||||
init(impl: WebEmbedImplementation, intrinsicDimensions: CGSize, openUrl: @escaping (URL) -> Void) {
|
||||
self.impl = impl
|
||||
self.intrinsicDimensions = intrinsicDimensions
|
||||
self.openUrl = openUrl
|
||||
|
||||
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()
|
||||
configuration.allowsInlineMediaPlayback = true
|
||||
@ -112,6 +118,8 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
||||
|
||||
self.webView.navigationDelegate = self
|
||||
self.webView.scrollView.isScrollEnabled = false
|
||||
self.webView.allowsLinkPreview = false
|
||||
self.webView.allowsBackForwardNavigationGestures = false
|
||||
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
||||
self.webView.accessibilityIgnoresInvertColors = true
|
||||
self.webView.scrollView.contentInsetAdjustmentBehavior = .never
|
||||
@ -159,7 +167,7 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
||||
|
||||
print("w")
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
@ -179,6 +187,9 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
||||
} else if let _ = navigationAction.targetFrame {
|
||||
decisionHandler(.allow)
|
||||
} else {
|
||||
if let url = navigationAction.request.url, url.absoluteString.contains("youtube") {
|
||||
self.openUrl(url)
|
||||
}
|
||||
decisionHandler(.cancel)
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,9 @@ public final class WebEmbedVideoContent: UniversalVideoContent {
|
||||
public let dimensions: CGSize
|
||||
public let duration: Int32
|
||||
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 {
|
||||
return nil
|
||||
}
|
||||
@ -30,10 +31,11 @@ public final class WebEmbedVideoContent: UniversalVideoContent {
|
||||
self.dimensions = webpageContent.embedSize?.cgSize ?? CGSize(width: 128.0, height: 128.0)
|
||||
self.duration = Int32(webpageContent.duration ?? (0 as Int))
|
||||
self.forcedTimestamp = forcedTimestamp
|
||||
self.openUrl = openUrl
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
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
|
||||
|
||||
if let embedSize = webpageContent.embedSize {
|
||||
@ -83,7 +85,7 @@ final class WebEmbedVideoContentNode: ASDisplayNode, UniversalVideoContentNode {
|
||||
|
||||
let embedType = webEmbedType(content: webpageContent, forcedTimestamp: forcedTimestamp)
|
||||
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()
|
||||
|
||||
|
@ -174,8 +174,8 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation {
|
||||
updateStatus(self.status)
|
||||
|
||||
let html = String(format: htmlTemplate, paramsJson)
|
||||
webView.loadHTMLString(html, baseURL: URL(string: "https://youtube.com/"))
|
||||
webView.isUserInteractionEnabled = false
|
||||
webView.loadHTMLString(html, baseURL: URL(string: "https://messenger.telegram.org"))
|
||||
// webView.isUserInteractionEnabled = false
|
||||
|
||||
userContentController.addUserScript(WKUserScript(source: userScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user