Browser improvements

This commit is contained in:
Ilya Laktyushin 2024-08-09 06:34:09 +02:00
parent bbe90fcadb
commit d17391ad9b
5 changed files with 116 additions and 40 deletions

View File

@ -60,6 +60,7 @@ final class BrowserDocumentContent: UIView, BrowserContent, WKNavigationDelegate
} }
var title: String = "file" var title: String = "file"
var url = ""
if let path = self.context.account.postbox.mediaBox.completedResourcePath(file.resource) { if let path = self.context.account.postbox.mediaBox.completedResourcePath(file.resource) {
var updatedPath = path var updatedPath = path
if let fileName = file.fileName { if let fileName = file.fileName {
@ -67,13 +68,14 @@ final class BrowserDocumentContent: UIView, BrowserContent, WKNavigationDelegate
updatedPath = tempFile.path updatedPath = tempFile.path
self.tempFile = tempFile self.tempFile = tempFile
title = fileName title = fileName
url = updatedPath
} }
let request = URLRequest(url: URL(fileURLWithPath: updatedPath)) let request = URLRequest(url: URL(fileURLWithPath: updatedPath))
self.webView.load(request) self.webView.load(request)
} }
self._state = BrowserContentState(title: title, url: "", estimatedProgress: 0.0, readingProgress: 0.0, contentType: .document) self._state = BrowserContentState(title: title, url: url, estimatedProgress: 0.0, readingProgress: 0.0, contentType: .document)
self.statePromise = Promise<BrowserContentState>(self._state) self.statePromise = Promise<BrowserContentState>(self._state)
super.init(frame: .zero) super.init(frame: .zero)

View File

@ -71,13 +71,21 @@ final class BrowserPdfContent: UIView, BrowserContent, UIScrollViewDelegate, PDF
self.pdfView.displayDirection = .vertical self.pdfView.displayDirection = .vertical
self.pdfView.autoScales = true self.pdfView.autoScales = true
var title: String = "file" var title = "file"
if let path = self.context.account.postbox.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) { var url = ""
self.pdfView.document = PDFDocument(data: data) if let path = self.context.account.postbox.mediaBox.completedResourcePath(file.resource) {
title = file.fileName ?? "file" var updatedPath = path
if let fileName = file.fileName {
let tempFile = TempBox.shared.file(path: path, fileName: fileName)
updatedPath = tempFile.path
self.tempFile = tempFile
title = fileName
url = updatedPath
}
self.pdfView.document = PDFDocument(url: URL(fileURLWithPath: updatedPath))
} }
self._state = BrowserContentState(title: title, url: "", estimatedProgress: 0.0, readingProgress: 0.0, contentType: .document) self._state = BrowserContentState(title: title, url: url, estimatedProgress: 0.0, readingProgress: 0.0, contentType: .document)
self.statePromise = Promise<BrowserContentState>(self._state) self.statePromise = Promise<BrowserContentState>(self._state)
super.init(frame: .zero) super.init(frame: .zero)

View File

@ -28,6 +28,7 @@ private final class BrowserScreenComponent: CombinedComponent {
let context: AccountContext let context: AccountContext
let contentState: BrowserContentState? let contentState: BrowserContentState?
let presentationState: BrowserPresentationState let presentationState: BrowserPresentationState
let canShare: Bool
let performAction: ActionSlot<BrowserScreen.Action> let performAction: ActionSlot<BrowserScreen.Action>
let performHoldAction: (UIView, ContextGesture?, BrowserScreen.Action) -> Void let performHoldAction: (UIView, ContextGesture?, BrowserScreen.Action) -> Void
let panelCollapseFraction: CGFloat let panelCollapseFraction: CGFloat
@ -36,6 +37,7 @@ private final class BrowserScreenComponent: CombinedComponent {
context: AccountContext, context: AccountContext,
contentState: BrowserContentState?, contentState: BrowserContentState?,
presentationState: BrowserPresentationState, presentationState: BrowserPresentationState,
canShare: Bool,
performAction: ActionSlot<BrowserScreen.Action>, performAction: ActionSlot<BrowserScreen.Action>,
performHoldAction: @escaping (UIView, ContextGesture?, BrowserScreen.Action) -> Void, performHoldAction: @escaping (UIView, ContextGesture?, BrowserScreen.Action) -> Void,
panelCollapseFraction: CGFloat panelCollapseFraction: CGFloat
@ -43,6 +45,7 @@ private final class BrowserScreenComponent: CombinedComponent {
self.context = context self.context = context
self.contentState = contentState self.contentState = contentState
self.presentationState = presentationState self.presentationState = presentationState
self.canShare = canShare
self.performAction = performAction self.performAction = performAction
self.performHoldAction = performHoldAction self.performHoldAction = performHoldAction
self.panelCollapseFraction = panelCollapseFraction self.panelCollapseFraction = panelCollapseFraction
@ -58,6 +61,9 @@ private final class BrowserScreenComponent: CombinedComponent {
if lhs.presentationState != rhs.presentationState { if lhs.presentationState != rhs.presentationState {
return false return false
} }
if lhs.canShare != rhs.canShare {
return false
}
if lhs.panelCollapseFraction != rhs.panelCollapseFraction { if lhs.panelCollapseFraction != rhs.panelCollapseFraction {
return false return false
} }
@ -260,25 +266,27 @@ private final class BrowserScreenComponent: CombinedComponent {
), ),
at: 0 at: 0
) )
navigationRightItems.insert( if context.component.canShare {
AnyComponentWithIdentity( navigationRightItems.insert(
id: "share", AnyComponentWithIdentity(
component: AnyComponent( id: "share",
Button( component: AnyComponent(
content: AnyComponent( Button(
BundleIconComponent( content: AnyComponent(
name: "Chat List/NavigationShare", BundleIconComponent(
tintColor: environment.theme.rootController.navigationBar.accentTextColor name: "Chat List/NavigationShare",
) tintColor: environment.theme.rootController.navigationBar.accentTextColor
), )
action: { ),
performAction.invoke(.share) action: {
} performAction.invoke(.share)
}
)
) )
) ),
), at: 0
at: 0 )
) }
if canOpenIn { if canOpenIn {
navigationRightItems.append( navigationRightItems.append(
AnyComponentWithIdentity( AnyComponentWithIdentity(
@ -359,6 +367,7 @@ private final class BrowserScreenComponent: CombinedComponent {
canGoBack: context.component.contentState?.canGoBack ?? false, canGoBack: context.component.contentState?.canGoBack ?? false,
canGoForward: context.component.contentState?.canGoForward ?? false, canGoForward: context.component.contentState?.canGoForward ?? false,
canOpenIn: canOpenIn, canOpenIn: canOpenIn,
canShare: context.component.canShare,
isDocument: context.component.contentState?.contentType == .document, isDocument: context.component.contentState?.contentType == .document,
performAction: performAction, performAction: performAction,
performHoldAction: performHoldAction performHoldAction: performHoldAction
@ -617,7 +626,19 @@ public class BrowserScreen: ViewController, MinimizableController {
case .minimize: case .minimize:
self.minimize() self.minimize()
case .openIn: case .openIn:
self.context.sharedContext.applicationBindings.openUrl(url) var processed = false
if let controller = self.controller {
switch controller.subject {
case let .document(file, canShare), let .pdfDocument(file, canShare):
processed = true
controller.openDocument(file, canShare)
default:
break
}
}
if !processed {
self.context.sharedContext.applicationBindings.openUrl(url)
}
case .openSettings: case .openSettings:
self.openSettings() self.openSettings()
case let .updateSearchActive(active): case let .updateSearchActive(active):
@ -806,9 +827,9 @@ public class BrowserScreen: ViewController, MinimizableController {
self.openPeer(peer) self.openPeer(peer)
} }
browserContent = instantPageContent browserContent = instantPageContent
case let .document(file): case let .document(file, _):
browserContent = BrowserDocumentContent(context: self.context, presentationData: self.presentationData, file: file) browserContent = BrowserDocumentContent(context: self.context, presentationData: self.presentationData, file: file)
case let .pdfDocument(file): case let .pdfDocument(file, _):
browserContent = BrowserPdfContent(context: self.context, presentationData: self.presentationData, file: file) browserContent = BrowserPdfContent(context: self.context, presentationData: self.presentationData, file: file)
} }
browserContent.pushContent = { [weak self] content in browserContent.pushContent = { [weak self] content in
@ -1087,8 +1108,16 @@ public class BrowserScreen: ViewController, MinimizableController {
openInUrl = url openInUrl = url
} }
let canOpenIn = !(self.contentState?.url.hasPrefix("tonsite") ?? false) let canOpenIn = !(self.contentState?.url.hasPrefix("tonsite") ?? false)
var canShare = true
if let controller = self.controller {
switch controller.subject {
case let .document(_, canShareValue), let .pdfDocument(_, canShareValue):
canShare = canShareValue
default:
break
}
}
var items: [ContextMenuItem] = [] var items: [ContextMenuItem] = []
if contentState.contentType == .document, contentState.title.lowercased().hasSuffix(".pdf") { if contentState.contentType == .document, contentState.title.lowercased().hasSuffix(".pdf") {
@ -1124,7 +1153,7 @@ public class BrowserScreen: ViewController, MinimizableController {
}))) })))
} }
if !layout.metrics.isTablet { if canShare && !layout.metrics.isTablet {
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.WebBrowser_Share, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Share"), color: theme.contextMenu.primaryColor) }, action: { (controller, action) in items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.WebBrowser_Share, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Share"), color: theme.contextMenu.primaryColor) }, action: { (controller, action) in
performAction.invoke(.share) performAction.invoke(.share)
action(.default) action(.default)
@ -1295,6 +1324,16 @@ public class BrowserScreen: ViewController, MinimizableController {
return self?.controller return self?.controller
} }
) )
var canShare = true
if let controller = self.controller {
switch controller.subject {
case let .document(_, canShareValue), let .pdfDocument(_, canShareValue):
canShare = canShareValue
default:
break
}
}
let componentSize = self.componentHost.update( let componentSize = self.componentHost.update(
transition: transition, transition: transition,
@ -1303,6 +1342,7 @@ public class BrowserScreen: ViewController, MinimizableController {
context: self.context, context: self.context,
contentState: self.contentState, contentState: self.contentState,
presentationState: self.presentationState, presentationState: self.presentationState,
canShare: canShare,
performAction: self.performAction, performAction: self.performAction,
performHoldAction: { [weak self] view, gesture, action in performHoldAction: { [weak self] view, gesture, action in
if let self { if let self {
@ -1379,15 +1419,17 @@ public class BrowserScreen: ViewController, MinimizableController {
public enum Subject { public enum Subject {
case webPage(url: String) case webPage(url: String)
case instantPage(webPage: TelegramMediaWebpage, anchor: String?, sourceLocation: InstantPageSourceLocation) case instantPage(webPage: TelegramMediaWebpage, anchor: String?, sourceLocation: InstantPageSourceLocation)
case document(file: TelegramMediaFile) case document(file: TelegramMediaFile, canShare: Bool)
case pdfDocument(file: TelegramMediaFile) case pdfDocument(file: TelegramMediaFile, canShare: Bool)
} }
private let context: AccountContext private let context: AccountContext
private let subject: Subject fileprivate let subject: Subject
private var preferredConfiguration: WKWebViewConfiguration? private var preferredConfiguration: WKWebViewConfiguration?
private var openPreviousOnClose = false private var openPreviousOnClose = false
public var openDocument: (TelegramMediaFile, Bool) -> Void = { _, _ in }
private var validLayout: ContainerViewLayout? private var validLayout: ContainerViewLayout?
public static let supportedDocumentMimeTypes: [String] = [ public static let supportedDocumentMimeTypes: [String] = [

View File

@ -125,6 +125,7 @@ final class NavigationToolbarContentComponent: CombinedComponent {
let canGoBack: Bool let canGoBack: Bool
let canGoForward: Bool let canGoForward: Bool
let canOpenIn: Bool let canOpenIn: Bool
let canShare: Bool
let isDocument: Bool let isDocument: Bool
let performAction: ActionSlot<BrowserScreen.Action> let performAction: ActionSlot<BrowserScreen.Action>
let performHoldAction: (UIView, ContextGesture?, BrowserScreen.Action) -> Void let performHoldAction: (UIView, ContextGesture?, BrowserScreen.Action) -> Void
@ -135,6 +136,7 @@ final class NavigationToolbarContentComponent: CombinedComponent {
canGoBack: Bool, canGoBack: Bool,
canGoForward: Bool, canGoForward: Bool,
canOpenIn: Bool, canOpenIn: Bool,
canShare: Bool,
isDocument: Bool, isDocument: Bool,
performAction: ActionSlot<BrowserScreen.Action>, performAction: ActionSlot<BrowserScreen.Action>,
performHoldAction: @escaping (UIView, ContextGesture?, BrowserScreen.Action) -> Void performHoldAction: @escaping (UIView, ContextGesture?, BrowserScreen.Action) -> Void
@ -144,6 +146,7 @@ final class NavigationToolbarContentComponent: CombinedComponent {
self.canGoBack = canGoBack self.canGoBack = canGoBack
self.canGoForward = canGoForward self.canGoForward = canGoForward
self.canOpenIn = canOpenIn self.canOpenIn = canOpenIn
self.canShare = canShare
self.isDocument = isDocument self.isDocument = isDocument
self.performAction = performAction self.performAction = performAction
self.performHoldAction = performHoldAction self.performHoldAction = performHoldAction
@ -165,6 +168,9 @@ final class NavigationToolbarContentComponent: CombinedComponent {
if lhs.canOpenIn != rhs.canOpenIn { if lhs.canOpenIn != rhs.canOpenIn {
return false return false
} }
if lhs.canShare != rhs.canShare {
return false
}
if lhs.isDocument != rhs.isDocument { if lhs.isDocument != rhs.isDocument {
return false return false
} }
@ -188,13 +194,17 @@ final class NavigationToolbarContentComponent: CombinedComponent {
let sideInset: CGFloat = 5.0 let sideInset: CGFloat = 5.0
let buttonSize = CGSize(width: 50.0, height: availableSize.height) let buttonSize = CGSize(width: 50.0, height: availableSize.height)
var buttonCount = 4 var buttonCount = 3
if context.component.canShare {
buttonCount += 1
}
if context.component.canOpenIn { if context.component.canOpenIn {
buttonCount += 1 buttonCount += 1
} }
let spacing = (availableSize.width - buttonSize.width * CGFloat(buttonCount) - sideInset * 2.0) / CGFloat(buttonCount - 1) let spacing = (availableSize.width - buttonSize.width * CGFloat(buttonCount) - sideInset * 2.0) / CGFloat(buttonCount - 1)
let canShare = context.component.canShare
let share = share.update( let share = share.update(
component: Button( component: Button(
content: AnyComponent( content: AnyComponent(
@ -204,7 +214,9 @@ final class NavigationToolbarContentComponent: CombinedComponent {
) )
), ),
action: { action: {
performAction.invoke(.share) if canShare {
performAction.invoke(.share)
}
} }
).minSize(buttonSize), ).minSize(buttonSize),
availableSize: buttonSize, availableSize: buttonSize,
@ -212,9 +224,15 @@ final class NavigationToolbarContentComponent: CombinedComponent {
) )
if context.component.isDocument { if context.component.isDocument {
context.add(share if !context.component.canShare {
.position(CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0)) context.add(share
) .position(CGPoint(x: availableSize.width / 2.0, y: 10000.0))
)
} else {
context.add(share
.position(CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0))
)
}
let search = search.update( let search = search.update(
component: Button( component: Button(

View File

@ -231,17 +231,23 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
params.present(controller, nil) params.present(controller, nil)
} else if let rootController = params.navigationController?.view.window?.rootViewController { } else if let rootController = params.navigationController?.view.window?.rootViewController {
let proceed = { let proceed = {
let canShare = !params.message.isCopyProtected()
if BrowserScreen.supportedDocumentMimeTypes.contains(file.mimeType) { if BrowserScreen.supportedDocumentMimeTypes.contains(file.mimeType) {
let subject: BrowserScreen.Subject let subject: BrowserScreen.Subject
if file.mimeType == "application/pdf" { if file.mimeType == "application/pdf" {
subject = .pdfDocument(file: file) subject = .pdfDocument(file: file, canShare: canShare)
} else { } else {
subject = .document(file: file) subject = .document(file: file, canShare: canShare)
} }
let controller = BrowserScreen(context: params.context, subject: subject) let controller = BrowserScreen(context: params.context, subject: subject)
controller.openDocument = { file, canShare in
controller.dismiss()
presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file, canShare: canShare)
}
params.navigationController?.pushViewController(controller) params.navigationController?.pushViewController(controller)
} else { } else {
presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file, canShare: !params.message.isCopyProtected()) presentDocumentPreviewController(rootController: rootController, theme: presentationData.theme, strings: presentationData.strings, postbox: params.context.account.postbox, file: file, canShare: canShare)
} }
} }
if file.mimeType.contains("image/svg") { if file.mimeType.contains("image/svg") {