mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Browser improvements
This commit is contained in:
parent
bbe90fcadb
commit
d17391ad9b
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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] = [
|
||||||
|
@ -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(
|
||||||
|
@ -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") {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user