Add share sheet

This commit is contained in:
2020-12-22 15:25:32 +01:00
parent cfab1c12f1
commit c8f05f44a6
5 changed files with 87 additions and 41 deletions

View File

@@ -36,6 +36,7 @@
95CA31B7255C1EE000AC095B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95CA31B6255C1EE000AC095B /* Preview Assets.xcassets */; };
95CA31C0255C28C300AC095B /* CircularView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95CA31BF255C28C300AC095B /* CircularView.swift */; };
95DB71AB258A1C1500A78033 /* CarteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95DB71AA258A1C1500A78033 /* CarteView.swift */; };
95E58FBB2592195B00689C37 /* ShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95E58FBA2592195B00689C37 /* ShareSheet.swift */; };
95F6666E2590D712006DE74F /* URLUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95F6666D2590D712006DE74F /* URLUtils.swift */; };
/* End PBXBuildFile section */
@@ -87,6 +88,7 @@
95CA31B8255C1EE000AC095B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
95CA31BF255C28C300AC095B /* CircularView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularView.swift; sourceTree = "<group>"; };
95DB71AA258A1C1500A78033 /* CarteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarteView.swift; sourceTree = "<group>"; };
95E58FBA2592195B00689C37 /* ShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheet.swift; sourceTree = "<group>"; };
95F6666D2590D712006DE74F /* URLUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLUtils.swift; sourceTree = "<group>"; };
976621FBDDCA894FD23FBA8B /* Pods-circolapp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-circolapp.release.xcconfig"; path = "Target Support Files/Pods-circolapp/Pods-circolapp.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -137,8 +139,9 @@
95CA31B1255C1EDE00AC095B /* ContentView.swift */,
95CA31BF255C28C300AC095B /* CircularView.swift */,
95BC3BF72572BCF900F24400 /* AttachmentView.swift */,
9512D3C0257AB4F60023C3A1 /* NewReminderView.swift */,
95E58FBA2592195B00689C37 /* ShareSheet.swift */,
955B7A0D257D098C0091B1F9 /* SearchBar.swift */,
9512D3C0257AB4F60023C3A1 /* NewReminderView.swift */,
955B7A0F257D10A70091B1F9 /* ViewControllerResolver.swift */,
9554BDB7257E498F00D8925B /* OnboardingView.swift */,
954AF8F52588A5C300666D0C /* CircularList.swift */,
@@ -190,12 +193,12 @@
95CA31AF255C1EDE00AC095B /* AppDelegate.swift */,
952DEDDE2576F8DC001DF85D /* SceneDelegate.swift */,
954E683C2574ED9E0034EBA8 /* UserDefaultsExtensions.swift */,
95F6666D2590D712006DE74F /* URLUtils.swift */,
953DDE7D2580312500C457CE /* LaunchScreen.storyboard */,
95CA31B8255C1EE000AC095B /* Info.plist */,
95906F4C257510370060F5D0 /* GoogleService-Info.plist */,
95906F47257506360060F5D0 /* Assets.xcassets */,
95CA31B5255C1EE000AC095B /* Preview Content */,
95F6666D2590D712006DE74F /* URLUtils.swift */,
);
path = circolapp;
sourceTree = "<group>";
@@ -375,6 +378,7 @@
954E68352574E3890034EBA8 /* iOSServerApi.swift in Sources */,
95DB71AB258A1C1500A78033 /* CarteView.swift in Sources */,
950C1784258E582E00B2DBFE /* PadView.swift in Sources */,
95E58FBB2592195B00689C37 /* ShareSheet.swift in Sources */,
954AF8F82588A5CF00666D0C /* FavouritesList.swift in Sources */,
954AF8F62588A5C300666D0C /* CircularList.swift in Sources */,
954AF8FD2588A61000666D0C /* FavouritesViewModel.swift in Sources */,

View File

@@ -18,10 +18,19 @@
import Foundation
import UIKit
import SwiftUI
class URLUtils {
static func openUrl(url: String) {
guard let safeUrl = URL(string: url.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!) else { return }
UIApplication.shared.open(safeUrl)
}
static func shareSheetView(url: String) -> some View {
if let safeUrl = URL(string: url.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!) {
return ShareSheet(activityItems: [safeUrl])
} else {
return ShareSheet(activityItems: [url])
}
}
}

View File

@@ -20,6 +20,9 @@ import SwiftUI
import Shared
struct AttachmentView: View {
@State private var sharingPhone: Bool = false
@State private var sharingPad: Bool = false
var attachmentName: String
var attachmentUrl: String
@@ -43,34 +46,26 @@ struct AttachmentView: View {
.buttonStyle(BorderlessButtonStyle())
Button(action: {
guard let url = URL(string: attachmentUrl) else { return }
let downloadTask = URLSession.shared.downloadTask(with: url) {
urlOrNil, responseOrNil, errorOrNil in
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(fileURL.lastPathComponent)
try FileManager.default.moveItem(at: fileURL, to: savedURL)
} catch {
print ("file error: \(error)")
}
if UIDevice.current.userInterfaceIdiom == .phone {
sharingPhone = true
} else {
sharingPad = true
}
downloadTask.resume()
}) {
Image(systemName: "square.and.arrow.down.fill")
Image(systemName: "square.and.arrow.up.fill")
.resizable()
.scaledToFit()
.frame(width: 20.0, height: 20.0)
.padding(8.0)
}
.buttonStyle(BorderlessButtonStyle())
.sheet(isPresented: $sharingPhone) {
URLUtils.shareSheetView(url: attachmentUrl)
}
.popover(isPresented: $sharingPad) {
URLUtils.shareSheetView(url: attachmentUrl)
}
}
}
}

View File

@@ -21,7 +21,10 @@ import Shared
struct CircularView: View {
@State private var creatingReminder: Bool = false
@State private var sharingPhone: Bool = false
@State private var sharingPad: Bool = false
@State private var showDetail = false
var circular: Circular
var body: some View {
@@ -61,33 +64,24 @@ struct CircularView: View {
Spacer()
Button(action: {
guard let url = URL(string: circular.url) else { return }
let downloadTask = URLSession.shared.downloadTask(with: url) {
urlOrNil, responseOrNil, errorOrNil in
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(fileURL.lastPathComponent)
try FileManager.default.moveItem(at: fileURL, to: savedURL)
} catch {
print ("file error: \(error)")
if UIDevice.current.userInterfaceIdiom == .phone {
sharingPhone = true
} else {
sharingPad = true
}
}
downloadTask.resume()
}) {
Image(systemName: "square.and.arrow.down.fill")
Image(systemName: "square.and.arrow.up.fill")
.resizable()
.scaledToFit()
.frame(width: 20.0, height: 20.0)
}
.buttonStyle(BorderlessButtonStyle())
.sheet(isPresented: $sharingPhone) {
URLUtils.shareSheetView(url: circular.url)
}
.popover(isPresented: $sharingPad) {
URLUtils.shareSheetView(url: circular.url)
}
Spacer()

View File

@@ -0,0 +1,44 @@
/*
* Circolapp
* Copyright (C) 2019-2020 Matteo Schiff
*
* This program 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
* (at your option) any later version.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation
import UIKit
import SwiftUI
struct ShareSheet: UIViewControllerRepresentable {
typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
let activityItems: [Any]
let applicationActivities: [UIActivity]? = nil
let excludedActivityTypes: [UIActivity.ActivityType]? = nil
let callback: Callback? = nil
func makeUIViewController(context: Context) -> UIActivityViewController {
let controller = UIActivityViewController(
activityItems: activityItems,
applicationActivities: applicationActivities)
controller.excludedActivityTypes = excludedActivityTypes
controller.completionWithItemsHandler = callback
controller.isModalInPresentation = true
return controller
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
// nothing to do here
}
}