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
switch controller.subject {
case let .webPage(url):
content = BrowserWebContent(url: url)
content = BrowserWebContent(context: controller.context, url: url)
}
self.content = content

View File

@ -10,6 +10,76 @@ import AccountContext
import WebKit
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 {
private let webView: WKWebView
@ -22,9 +92,14 @@ final class BrowserWebContent: UIView, BrowserContent, UIScrollViewDelegate {
var onScrollingUpdate: (ContentScrollingUpdate) -> Void = { _ in }
init(url: String) {
init(context: AccountContext, url: String) {
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.allowsLinkPreview = false

View File

@ -94,7 +94,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case experimentalCompatibility(Bool)
case enableDebugDataDisplay(Bool)
case acceleratedStickers(Bool)
case inlineForums(Bool)
case browserExperiment(Bool)
case localTranscription(Bool)
case enableReactionOverrides(Bool)
case storiesExperiment(Bool)
@ -126,7 +126,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.web.rawValue
case .keepChatNavigationStack, .skipReadHistory, .dustEffect, .crashOnSlowQueries, .crashOnMemoryPressure:
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
case .logTranslationRecognition, .resetTranslationStates:
return DebugControllerSection.translation.rawValue
@ -217,7 +217,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 38
case .acceleratedStickers:
return 39
case .inlineForums:
case .browserExperiment:
return 40
case .localTranscription:
return 41
@ -1235,12 +1235,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
})
}).start()
})
case let .inlineForums(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Inline Forums", value: value, sectionId: self.section, style: .blocks, updated: { value in
case let .browserExperiment(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Inline UI", value: value, sectionId: self.section, style: .blocks, updated: { value in
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings
settings.inlineForums = value
settings.browserExperiment = value
return PreferencesEntry(settings)
})
}).start()
@ -1438,7 +1438,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present
entries.append(.experimentalCompatibility(experimentalSettings.experimentalCompatibility))
entries.append(.enableDebugDataDisplay(experimentalSettings.enableDebugDataDisplay))
entries.append(.acceleratedStickers(experimentalSettings.acceleratedStickers))
entries.append(.inlineForums(experimentalSettings.inlineForums))
entries.append(.browserExperiment(experimentalSettings.browserExperiment))
entries.append(.localTranscription(experimentalSettings.localTranscription))
if case .internal = sharedContext.applicationBindings.appBuildType {
entries.append(.enableReactionOverrides(experimentalSettings.enableReactionOverrides))

View File

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

View File

@ -62,7 +62,8 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n
if let controller = controller {
switch result {
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):
openResolvedPeerImpl(peer.flatMap(EnginePeer.init), navigation)
case let .botStart(peer, payload):

View File

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