Share PDF added

This commit is contained in:
Balazs Perlaki-Horvath 2024-04-15 00:00:09 +02:00
parent 24aab85522
commit fa1aa99ce3
6 changed files with 164 additions and 1 deletions

View File

@ -41,6 +41,7 @@ struct Kiwix: App {
.environmentObject(navigation)
.modifier(AlertHandler())
.modifier(OpenFileHandler())
.modifier(SharePDFHandler())
.modifier(SaveContentHandler())
.onChange(of: scenePhase) { newValue in
guard newValue == .inactive else { return }

View File

@ -175,6 +175,7 @@ struct RootView: View {
.modifier(AlertHandler())
.modifier(OpenFileHandler())
.modifier(SaveContentHandler())
.modifier(SharePDFHandler())
.onOpenURL { url in
if url.isFileURL {
NotificationCenter.openFiles([url], context: .file)

View File

@ -41,4 +41,17 @@ extension URL {
init(appStoreReviewForName appName: String, appStoreID: String) {
self.init(string: "itms-apps://itunes.apple.com/us/app/\(appName)/\(appStoreID)?action=write-review")!
}
init(temporaryFileWithName fileName: String) {
let directory = FileManager.default.temporaryDirectory
if #available(macOS 13.0, iOS 16.0, *) {
self = directory.appending(path: fileName)
} else {
self = directory.appendingPathComponent(fileName)
}
}
func toTemporaryFileURL() -> URL? {
URL(temporaryFileWithName: lastPathComponent)
}
}

View File

@ -71,6 +71,7 @@ extension Notification.Name {
static let alert = Notification.Name("alert")
static let openFiles = Notification.Name("openFiles")
static let openURL = Notification.Name("openURL")
static let sharePDF = Notification.Name("sharePDF")
static let saveContent = Notification.Name("saveContent")
static let toggleSidebar = Notification.Name("toggleSidebar")
}
@ -89,6 +90,10 @@ extension NotificationCenter {
NotificationCenter.default.post(name: .openFiles, object: nil, userInfo: ["urls": urls, "context": context])
}
static func sharePDF(_ data: Data, fileName: String) {
NotificationCenter.default.post(name: .sharePDF, object: nil, userInfo: ["data": data, "fileName": fileName])
}
static func saveContent(url: URL) {
NotificationCenter.default.post(name: .saveContent, object: nil, userInfo: ["url": url])
}

View File

@ -21,7 +21,15 @@ struct ShareButton: View {
var body: some View {
Button {
debugPrint("share this")
Task {
guard let browserURLName = browser.webView.url?.lastPathComponent else {
return
}
guard let pdfData = try? await browser.webView.pdf() else {
return
}
NotificationCenter.sharePDF(pdfData, fileName: browserURLName)
}
} label: {
Label {
Text("Share".localized)

View File

@ -0,0 +1,135 @@
// This file is part of Kiwix for iOS & macOS.
//
// Kiwix is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// any later version.
//
// Kiwix is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kiwix; If not, see https://www.gnu.org/licenses/.
import SwiftUI
/// On receiving pdf content and a file name, it gives the ability to share it
struct SharePDFHandler: ViewModifier {
private let sharePDF = NotificationCenter.default.publisher(for: .sharePDF)
@State private var temporaryURL: URL?
func body(content: Content) -> some View {
content.onReceive(sharePDF) { notification in
guard let userInfo = notification.userInfo,
let pdfData = userInfo["data"] as? Data,
let fileName = userInfo["fileName"] as? String,
let tempFileName = fileName.split(separator: ".").first?.appending(".pdf") else {
return
}
let tempFileURL = URL(temporaryFileWithName: tempFileName)
guard (try? pdfData.write(to: tempFileURL)) != nil else {
temporaryURL = nil
return
}
temporaryURL = tempFileURL
}
#if os(iOS)
.sheet(
isPresented: Binding<Bool>.constant($temporaryURL.wrappedValue != nil),
onDismiss: {
if let temporaryURL {
try? FileManager.default.removeItem(at: temporaryURL)
}
temporaryURL = nil
}, content: {
#if os(iOS)
ActivityViewController(activityItems: [temporaryURL].compactMap { $0 })
#else
NSSharingServicePicker(items: [temporaryURL])
#endif
}
)
#else
.background(SharingsPicker(
isPresented: Binding<Bool>.constant($temporaryURL.wrappedValue != nil),
sharingItems: [temporaryURL].compactMap { $0 },
onDismiss: {
temporaryURL = nil
}
))
#endif
}
}
#if os(iOS)
struct ActivityViewController: UIViewControllerRepresentable {
var activityItems: [Any]
@Environment(\.dismiss) var dismissAction
func makeUIViewController(
context: UIViewControllerRepresentableContext<ActivityViewController>
) -> UIActivityViewController {
let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
controller.modalPresentationStyle = .pageSheet
controller.completionWithItemsHandler = { (_, _, _, _) in
self.dismissAction()
}
return controller
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
}
}
#endif
#if os(macOS)
struct SharingsPicker: NSViewRepresentable {
@Binding var isPresented: Bool {
didSet {
if isPresented == false {
onDismiss?()
}
}
}
var sharingItems: [Any] = []
let onDismiss: (() -> Void)?
func makeNSView(context: Context) -> NSView {
NSView()
}
func updateNSView(_ nsView: NSView, context: Context) {
if isPresented {
let picker = NSSharingServicePicker(items: sharingItems)
picker.delegate = context.coordinator
DispatchQueue.main.async { // call async, to not to block updates
picker.show(relativeTo: .zero, of: nsView, preferredEdge: .minX)
}
}
}
func makeCoordinator() -> Coordinator {
Coordinator(owner: self)
}
class Coordinator: NSObject, NSSharingServicePickerDelegate {
let owner: SharingsPicker
init(owner: SharingsPicker) {
self.owner = owner
}
func sharingServicePicker(_ sharingServicePicker: NSSharingServicePicker, didChoose service: NSSharingService?) {
sharingServicePicker.delegate = nil // << cleanup
owner.isPresented = false // << dismiss
owner.onDismiss?()
}
}
}
#endif