Various improvements

This commit is contained in:
Ilya Laktyushin
2024-07-23 22:01:56 +04:00
parent 31ba87fb0f
commit 1c7834ad57
43 changed files with 3867 additions and 459 deletions

View File

@@ -6,6 +6,7 @@ import Postbox
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
import PresentationDataUtils
import ItemListUI
import AccountContext
import OpenInExternalAppUI
@@ -13,12 +14,15 @@ import ItemListPeerActionItem
import UndoUI
import WebKit
import LinkPresentation
import CoreServices
import PersistentStringHash
private final class WebBrowserSettingsControllerArguments {
let context: AccountContext
let updateDefaultBrowser: (String?) -> Void
let clearCookies: () -> Void
let addException: () -> Void
let removeException: (String) -> Void
let clearExceptions: () -> Void
init(
@@ -26,12 +30,14 @@ private final class WebBrowserSettingsControllerArguments {
updateDefaultBrowser: @escaping (String?) -> Void,
clearCookies: @escaping () -> Void,
addException: @escaping () -> Void,
removeException: @escaping (String) -> Void,
clearExceptions: @escaping () -> Void
) {
self.context = context
self.updateDefaultBrowser = updateDefaultBrowser
self.clearCookies = clearCookies
self.addException = addException
self.removeException = removeException
self.clearExceptions = clearExceptions
}
}
@@ -66,7 +72,30 @@ private enum WebBrowserSettingsControllerEntry: ItemListNodeEntry {
}
}
var stableId: Int32 {
var stableId: UInt64 {
switch self {
case .browserHeader:
return 0
case let .browser(_, _, _, _, _, index):
return UInt64(1 + index)
case .clearCookies:
return 102
case .clearCookiesInfo:
return 103
case .exceptionsHeader:
return 104
case .exceptionsAdd:
return 105
case let .exception(_, _, exception):
return 2000 + exception.domain.persistentHashValue
case .exceptionsClear:
return 1000
case .exceptionsInfo:
return 1001
}
}
var sortId: Int32 {
switch self {
case .browserHeader:
return 0
@@ -149,7 +178,7 @@ private enum WebBrowserSettingsControllerEntry: ItemListNodeEntry {
}
static func <(lhs: WebBrowserSettingsControllerEntry, rhs: WebBrowserSettingsControllerEntry) -> Bool {
return lhs.stableId < rhs.stableId
return lhs.sortId < rhs.sortId
}
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
@@ -170,7 +199,9 @@ private enum WebBrowserSettingsControllerEntry: ItemListNodeEntry {
case let .exceptionsHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .exception(_, _, exception):
return WebBrowserDomainExceptionItem(presentationData: presentationData, context: arguments.context, title: exception.title, label: exception.domain, sectionId: self.section, style: .blocks)
return WebBrowserDomainExceptionItem(presentationData: presentationData, context: arguments.context, title: exception.title, label: exception.domain, icon: exception.icon, sectionId: self.section, style: .blocks, deleted: {
arguments.removeException(exception.domain)
})
case let .exceptionsAdd(_, text):
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.plusIconImage(presentationData.theme), title: text, sectionId: self.section, height: .generic, color: .accent, editing: false, action: {
arguments.addException()
@@ -207,7 +238,7 @@ private func webBrowserSettingsControllerEntries(context: AccountContext, presen
entries.append(.exceptionsAdd(presentationData.theme, presentationData.strings.WebBrowser_Exceptions_AddException))
var exceptionIndex: Int32 = 0
for exception in settings.exceptions {
for exception in settings.exceptions.reversed() {
entries.append(.exception(exceptionIndex, presentationData.theme, exception))
exceptionIndex += 1
}
@@ -225,6 +256,7 @@ private func webBrowserSettingsControllerEntries(context: AccountContext, presen
public func webBrowserSettingsController(context: AccountContext) -> ViewController {
var clearCookiesImpl: (() -> Void)?
var addExceptionImpl: (() -> Void)?
var removeExceptionImpl: ((String) -> Void)?
var clearExceptionsImpl: (() -> Void)?
let arguments = WebBrowserSettingsControllerArguments(
@@ -240,6 +272,9 @@ public func webBrowserSettingsController(context: AccountContext) -> ViewControl
addException: {
addExceptionImpl?()
},
removeException: { domain in
removeExceptionImpl?(domain)
},
clearExceptions: {
clearExceptionsImpl?()
}
@@ -261,6 +296,9 @@ public func webBrowserSettingsController(context: AccountContext) -> ViewControl
if previousSettings.defaultWebBrowser != settings.defaultWebBrowser {
animateChanges = true
}
if previousSettings.exceptions.count != settings.exceptions.count {
animateChanges = true
}
}
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.WebBrowser_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
@@ -290,9 +328,11 @@ public func webBrowserSettingsController(context: AccountContext) -> ViewControl
}
addExceptionImpl = { [weak controller] in
var dismissImpl: (() -> Void)?
let linkController = webBrowserDomainController(context: context, apply: { url in
if let url {
let _ = fetchDomainExceptionInfo(url: url).startStandalone(next: { newException in
let _ = (fetchDomainExceptionInfo(context: context, url: url)
|> deliverOnMainQueue).startStandalone(next: { newException in
let _ = updateWebBrowserSettingsInteractively(accountManager: context.sharedContext.accountManager, { currentSettings in
var currentExceptions = currentSettings.exceptions
for exception in currentExceptions {
@@ -303,18 +343,44 @@ public func webBrowserSettingsController(context: AccountContext) -> ViewControl
currentExceptions.append(newException)
return currentSettings.withUpdatedExceptions(currentExceptions)
}).start()
dismissImpl?()
})
}
})
dismissImpl = { [weak linkController] in
linkController?.view.endEditing(true)
linkController?.dismissAnimated()
}
controller?.present(linkController, in: .window(.root))
}
clearExceptionsImpl = {
removeExceptionImpl = { domain in
let _ = updateWebBrowserSettingsInteractively(accountManager: context.sharedContext.accountManager, { currentSettings in
return currentSettings.withUpdatedExceptions([])
let updatedExceptions = currentSettings.exceptions.filter { $0.domain != domain }
return currentSettings.withUpdatedExceptions(updatedExceptions)
}).start()
}
clearExceptionsImpl = { [weak controller] in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let alertController = textAlertController(
context: context,
updatedPresentationData: nil,
title: nil,
text: presentationData.strings.WebBrowser_Exceptions_ClearConfirmation_Text,
actions: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
TextAlertAction(type: .defaultAction, title: presentationData.strings.WebBrowser_Exceptions_ClearConfirmation_Clear, action: {
let _ = updateWebBrowserSettingsInteractively(accountManager: context.sharedContext.accountManager, { currentSettings in
return currentSettings.withUpdatedExceptions([])
}).start()
})
]
)
controller?.present(alertController, in: .window(.root))
}
return controller
}
@@ -333,22 +399,59 @@ private func cleanDomain(url: String) -> (domain: String, fullUrl: String) {
}
}
private func fetchDomainExceptionInfo(url: String) -> Signal<WebBrowserException, NoError> {
private func fetchDomainExceptionInfo(context: AccountContext, url: String) -> Signal<WebBrowserException, NoError> {
let (domain, domainUrl) = cleanDomain(url: url)
if #available(iOS 13.0, *), let url = URL(string: domainUrl) {
return Signal { subscriber in
let metadataProvider = LPMetadataProvider()
metadataProvider.shouldFetchSubresources = true
metadataProvider.startFetchingMetadata(for: url, completionHandler: { metadata, _ in
let title = metadata?.value(forKey: "_siteName") as? String ?? metadata?.title
subscriber.putNext(WebBrowserException(domain: domain, title: title ?? domain))
subscriber.putCompletion()
let completeWithImage: (Data?) -> Void = { imageData in
var image: TelegramMediaImage?
if let imageData, let parsedImage = UIImage(data: imageData) {
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
context.account.postbox.mediaBox.storeResourceData(resource.id, data: imageData)
image = TelegramMediaImage(
imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)),
representations: [
TelegramMediaImageRepresentation(
dimensions: PixelDimensions(width: Int32(parsedImage.size.width), height: Int32(parsedImage.size.height)),
resource: resource,
progressiveSizes: [],
immediateThumbnailData: nil,
hasVideo: false,
isPersonal: false
)
],
immediateThumbnailData: nil,
reference: nil,
partialReference: nil,
flags: []
)
}
let title = metadata?.value(forKey: "_siteName") as? String ?? metadata?.title
subscriber.putNext(WebBrowserException(domain: domain, title: title ?? domain, icon: image))
subscriber.putCompletion()
}
if let imageProvider = metadata?.iconProvider {
imageProvider.loadFileRepresentation(forTypeIdentifier: kUTTypeImage as String, completionHandler: { imageUrl, _ in
guard let imageUrl, let imageData = try? Data(contentsOf: imageUrl) else {
completeWithImage(nil)
return
}
completeWithImage(imageData)
})
} else {
completeWithImage(nil)
}
})
return ActionDisposable {
metadataProvider.cancel()
}
}
} else {
return .single(WebBrowserException(domain: domain, title: domain))
return .single(WebBrowserException(domain: domain, title: domain, icon: nil))
}
}