This commit is contained in:
Isaac 2024-04-04 16:55:10 +04:00
parent f6871b3a80
commit 9173f973a3
6 changed files with 103 additions and 17 deletions

View File

@ -282,7 +282,7 @@ public class BrowserScreen: ViewController {
let content: BrowserContent let content: BrowserContent
switch controller.subject { switch controller.subject {
case let .webPage(url): case let .webPage(url):
content = BrowserWebContent(url: url) content = BrowserWebContent(context: controller.context, url: url)
} }
self.content = content self.content = content

View File

@ -10,6 +10,76 @@ import AccountContext
import WebKit import WebKit
import AppBundle import AppBundle
private final class IpfsSchemeHandler: NSObject, WKURLSchemeHandler {
private final class PendingTask {
let sourceTask: any WKURLSchemeTask
var urlSessionTask: URLSessionTask?
let isCompleted = Atomic<Bool>(value: false)
init(sourceTask: any WKURLSchemeTask) {
self.sourceTask = sourceTask
var cleanUrl = sourceTask.request.url!.absoluteString
if let range = cleanUrl.range(of: "/ipfs/") {
cleanUrl = "ipfs://" + String(cleanUrl[range.upperBound...])
} else if let range = cleanUrl.range(of: "/ipns/") {
cleanUrl = "ipns://" + String(cleanUrl[range.upperBound...])
}
print("Load: \(cleanUrl)")
cleanUrl = cleanUrl.replacingOccurrences(of: "ipns://", with: "ipns/")
cleanUrl = cleanUrl.replacingOccurrences(of: "ipfs://", with: "ipfs/")
let mappedUrl = "https://cloudflare-ipfs.com/\(cleanUrl)"
let isCompleted = self.isCompleted
self.urlSessionTask = URLSession.shared.dataTask(with: URLRequest(url: URL(string: mappedUrl)!), completionHandler: { data, response, error in
if isCompleted.swap(true) {
return
}
if let error {
sourceTask.didFailWithError(error)
} else {
if let response {
sourceTask.didReceive(response)
}
if let data {
sourceTask.didReceive(data)
}
sourceTask.didFinish()
}
})
self.urlSessionTask?.resume()
}
func cancel() {
if let urlSessionTask = self.urlSessionTask {
self.urlSessionTask = nil
if !self.isCompleted.swap(true) {
switch urlSessionTask.state {
case .running, .suspended:
urlSessionTask.cancel()
default:
break
}
}
}
}
}
private var pendingTasks: [PendingTask] = []
func webView(_ webView: WKWebView, start urlSchemeTask: any WKURLSchemeTask) {
self.pendingTasks.append(PendingTask(sourceTask: urlSchemeTask))
}
func webView(_ webView: WKWebView, stop urlSchemeTask: any WKURLSchemeTask) {
if let index = self.pendingTasks.firstIndex(where: { $0.sourceTask === urlSchemeTask }) {
let task = self.pendingTasks[index]
self.pendingTasks.remove(at: index)
task.cancel()
}
}
}
final class BrowserWebContent: UIView, BrowserContent, UIScrollViewDelegate { final class BrowserWebContent: UIView, BrowserContent, UIScrollViewDelegate {
private let webView: WKWebView private let webView: WKWebView
@ -22,9 +92,14 @@ final class BrowserWebContent: UIView, BrowserContent, UIScrollViewDelegate {
var onScrollingUpdate: (ContentScrollingUpdate) -> Void = { _ in } var onScrollingUpdate: (ContentScrollingUpdate) -> Void = { _ in }
init(url: String) { init(context: AccountContext, url: String) {
let configuration = WKWebViewConfiguration() let configuration = WKWebViewConfiguration()
if context.sharedContext.immediateExperimentalUISettings.browserExperiment {
configuration.setURLSchemeHandler(IpfsSchemeHandler(), forURLScheme: "ipns")
configuration.setURLSchemeHandler(IpfsSchemeHandler(), forURLScheme: "ipfs")
}
self.webView = WKWebView(frame: CGRect(), configuration: configuration) self.webView = WKWebView(frame: CGRect(), configuration: configuration)
self.webView.allowsLinkPreview = false self.webView.allowsLinkPreview = false

View File

@ -94,7 +94,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case experimentalCompatibility(Bool) case experimentalCompatibility(Bool)
case enableDebugDataDisplay(Bool) case enableDebugDataDisplay(Bool)
case acceleratedStickers(Bool) case acceleratedStickers(Bool)
case inlineForums(Bool) case browserExperiment(Bool)
case localTranscription(Bool) case localTranscription(Bool)
case enableReactionOverrides(Bool) case enableReactionOverrides(Bool)
case storiesExperiment(Bool) case storiesExperiment(Bool)
@ -126,7 +126,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.web.rawValue return DebugControllerSection.web.rawValue
case .keepChatNavigationStack, .skipReadHistory, .dustEffect, .crashOnSlowQueries, .crashOnMemoryPressure: case .keepChatNavigationStack, .skipReadHistory, .dustEffect, .crashOnSlowQueries, .crashOnMemoryPressure:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .storiesExperiment, .storiesJpegExperiment, .playlistPlayback, .enableQuickReactionSwitch, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .inlineForums, .localTranscription, .enableReactionOverrides, .restorePurchases: case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .storiesExperiment, .storiesJpegExperiment, .playlistPlayback, .enableQuickReactionSwitch, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .browserExperiment, .localTranscription, .enableReactionOverrides, .restorePurchases:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .logTranslationRecognition, .resetTranslationStates: case .logTranslationRecognition, .resetTranslationStates:
return DebugControllerSection.translation.rawValue return DebugControllerSection.translation.rawValue
@ -217,7 +217,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 38 return 38
case .acceleratedStickers: case .acceleratedStickers:
return 39 return 39
case .inlineForums: case .browserExperiment:
return 40 return 40
case .localTranscription: case .localTranscription:
return 41 return 41
@ -1235,12 +1235,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
}) })
}).start() }).start()
}) })
case let .inlineForums(value): case let .browserExperiment(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Inline Forums", value: value, sectionId: self.section, style: .blocks, updated: { value in return ItemListSwitchItem(presentationData: presentationData, title: "Inline UI", value: value, sectionId: self.section, style: .blocks, updated: { value in
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings
settings.inlineForums = value settings.browserExperiment = value
return PreferencesEntry(settings) return PreferencesEntry(settings)
}) })
}).start() }).start()
@ -1438,7 +1438,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present
entries.append(.experimentalCompatibility(experimentalSettings.experimentalCompatibility)) entries.append(.experimentalCompatibility(experimentalSettings.experimentalCompatibility))
entries.append(.enableDebugDataDisplay(experimentalSettings.enableDebugDataDisplay)) entries.append(.enableDebugDataDisplay(experimentalSettings.enableDebugDataDisplay))
entries.append(.acceleratedStickers(experimentalSettings.acceleratedStickers)) entries.append(.acceleratedStickers(experimentalSettings.acceleratedStickers))
entries.append(.inlineForums(experimentalSettings.inlineForums)) entries.append(.browserExperiment(experimentalSettings.browserExperiment))
entries.append(.localTranscription(experimentalSettings.localTranscription)) entries.append(.localTranscription(experimentalSettings.localTranscription))
if case .internal = sharedContext.applicationBindings.appBuildType { if case .internal = sharedContext.applicationBindings.appBuildType {
entries.append(.enableReactionOverrides(experimentalSettings.enableReactionOverrides)) entries.append(.enableReactionOverrides(experimentalSettings.enableReactionOverrides))

View File

@ -988,7 +988,17 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
return return
} }
var isInternetUrl = false
if parsedUrl.scheme == "http" || parsedUrl.scheme == "https" { if parsedUrl.scheme == "http" || parsedUrl.scheme == "https" {
isInternetUrl = true
}
if context.sharedContext.immediateExperimentalUISettings.browserExperiment {
if parsedUrl.scheme == "ipfs" || parsedUrl.scheme == "ipns" {
isInternetUrl = true
}
}
if isInternetUrl {
if parsedUrl.host == "t.me" || parsedUrl.host == "telegram.me" { if parsedUrl.host == "t.me" || parsedUrl.host == "telegram.me" {
handleInternalUrl(parsedUrl.absoluteString) handleInternalUrl(parsedUrl.absoluteString)
} else { } else {
@ -1019,7 +1029,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
let _ = (settings let _ = (settings
|> deliverOnMainQueue).startStandalone(next: { settings in |> deliverOnMainQueue).startStandalone(next: { settings in
if settings.defaultWebBrowser == nil { if settings.defaultWebBrowser == nil {
if !"".isEmpty && isCompact { if isCompact && context.sharedContext.immediateExperimentalUISettings.browserExperiment {
let controller = BrowserScreen(context: context, subject: .webPage(url: parsedUrl.absoluteString)) let controller = BrowserScreen(context: context, subject: .webPage(url: parsedUrl.absoluteString))
navigationController?.pushViewController(controller) navigationController?.pushViewController(controller)
} else { } else {

View File

@ -62,7 +62,8 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n
if let controller = controller { if let controller = controller {
switch result { switch result {
case let .externalUrl(url): case let .externalUrl(url):
context.sharedContext.applicationBindings.openUrl(url) context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: false, presentationData: context.sharedContext.currentPresentationData.with({ $0 }), navigationController: controller.navigationController as? NavigationController, dismissInput: {
})
case let .peer(peer, navigation): case let .peer(peer, navigation):
openResolvedPeerImpl(peer.flatMap(EnginePeer.init), navigation) openResolvedPeerImpl(peer.flatMap(EnginePeer.init), navigation)
case let .botStart(peer, payload): case let .botStart(peer, payload):

View File

@ -42,7 +42,7 @@ public struct ExperimentalUISettings: Codable, Equatable {
public var inlineStickers: Bool public var inlineStickers: Bool
public var localTranscription: Bool public var localTranscription: Bool
public var enableReactionOverrides: Bool public var enableReactionOverrides: Bool
public var inlineForums: Bool public var browserExperiment: Bool
public var accountReactionEffectOverrides: [AccountReactionOverrides] public var accountReactionEffectOverrides: [AccountReactionOverrides]
public var accountStickerEffectOverrides: [AccountReactionOverrides] public var accountStickerEffectOverrides: [AccountReactionOverrides]
public var disableQuickReaction: Bool public var disableQuickReaction: Bool
@ -76,7 +76,7 @@ public struct ExperimentalUISettings: Codable, Equatable {
inlineStickers: false, inlineStickers: false,
localTranscription: false, localTranscription: false,
enableReactionOverrides: false, enableReactionOverrides: false,
inlineForums: false, browserExperiment: false,
accountReactionEffectOverrides: [], accountReactionEffectOverrides: [],
accountStickerEffectOverrides: [], accountStickerEffectOverrides: [],
disableQuickReaction: false, disableQuickReaction: false,
@ -111,7 +111,7 @@ public struct ExperimentalUISettings: Codable, Equatable {
inlineStickers: Bool, inlineStickers: Bool,
localTranscription: Bool, localTranscription: Bool,
enableReactionOverrides: Bool, enableReactionOverrides: Bool,
inlineForums: Bool, browserExperiment: Bool,
accountReactionEffectOverrides: [AccountReactionOverrides], accountReactionEffectOverrides: [AccountReactionOverrides],
accountStickerEffectOverrides: [AccountReactionOverrides], accountStickerEffectOverrides: [AccountReactionOverrides],
disableQuickReaction: Bool, disableQuickReaction: Bool,
@ -143,7 +143,7 @@ public struct ExperimentalUISettings: Codable, Equatable {
self.inlineStickers = inlineStickers self.inlineStickers = inlineStickers
self.localTranscription = localTranscription self.localTranscription = localTranscription
self.enableReactionOverrides = enableReactionOverrides self.enableReactionOverrides = enableReactionOverrides
self.inlineForums = inlineForums self.browserExperiment = browserExperiment
self.accountReactionEffectOverrides = accountReactionEffectOverrides self.accountReactionEffectOverrides = accountReactionEffectOverrides
self.accountStickerEffectOverrides = accountStickerEffectOverrides self.accountStickerEffectOverrides = accountStickerEffectOverrides
self.disableQuickReaction = disableQuickReaction self.disableQuickReaction = disableQuickReaction
@ -179,7 +179,7 @@ public struct ExperimentalUISettings: Codable, Equatable {
self.inlineStickers = (try container.decodeIfPresent(Int32.self, forKey: "inlineStickers") ?? 0) != 0 self.inlineStickers = (try container.decodeIfPresent(Int32.self, forKey: "inlineStickers") ?? 0) != 0
self.localTranscription = (try container.decodeIfPresent(Int32.self, forKey: "localTranscription") ?? 0) != 0 self.localTranscription = (try container.decodeIfPresent(Int32.self, forKey: "localTranscription") ?? 0) != 0
self.enableReactionOverrides = try container.decodeIfPresent(Bool.self, forKey: "enableReactionOverrides") ?? false self.enableReactionOverrides = try container.decodeIfPresent(Bool.self, forKey: "enableReactionOverrides") ?? false
self.inlineForums = try container.decodeIfPresent(Bool.self, forKey: "inlineForums") ?? false self.browserExperiment = try container.decodeIfPresent(Bool.self, forKey: "browserExperiment") ?? false
self.accountReactionEffectOverrides = (try? container.decodeIfPresent([AccountReactionOverrides].self, forKey: "accountReactionEffectOverrides")) ?? [] self.accountReactionEffectOverrides = (try? container.decodeIfPresent([AccountReactionOverrides].self, forKey: "accountReactionEffectOverrides")) ?? []
self.accountStickerEffectOverrides = (try? container.decodeIfPresent([AccountReactionOverrides].self, forKey: "accountStickerEffectOverrides")) ?? [] self.accountStickerEffectOverrides = (try? container.decodeIfPresent([AccountReactionOverrides].self, forKey: "accountStickerEffectOverrides")) ?? []
self.disableQuickReaction = try container.decodeIfPresent(Bool.self, forKey: "disableQuickReaction") ?? false self.disableQuickReaction = try container.decodeIfPresent(Bool.self, forKey: "disableQuickReaction") ?? false
@ -215,7 +215,7 @@ public struct ExperimentalUISettings: Codable, Equatable {
try container.encode((self.inlineStickers ? 1 : 0) as Int32, forKey: "inlineStickers") try container.encode((self.inlineStickers ? 1 : 0) as Int32, forKey: "inlineStickers")
try container.encode((self.localTranscription ? 1 : 0) as Int32, forKey: "localTranscription") try container.encode((self.localTranscription ? 1 : 0) as Int32, forKey: "localTranscription")
try container.encode(self.enableReactionOverrides, forKey: "enableReactionOverrides") try container.encode(self.enableReactionOverrides, forKey: "enableReactionOverrides")
try container.encode(self.inlineForums, forKey: "inlineForums") try container.encode(self.browserExperiment, forKey: "browserExperiment")
try container.encode(self.accountReactionEffectOverrides, forKey: "accountReactionEffectOverrides") try container.encode(self.accountReactionEffectOverrides, forKey: "accountReactionEffectOverrides")
try container.encode(self.accountStickerEffectOverrides, forKey: "accountStickerEffectOverrides") try container.encode(self.accountStickerEffectOverrides, forKey: "accountStickerEffectOverrides")
try container.encode(self.disableQuickReaction, forKey: "disableQuickReaction") try container.encode(self.disableQuickReaction, forKey: "disableQuickReaction")