closed #113 - import / export

This commit is contained in:
Trey t
2022-03-11 11:44:44 -06:00
parent 215ad5bb6d
commit 5583257f28
2 changed files with 133 additions and 2 deletions

View File

@@ -12,7 +12,7 @@
<key>Feels (macOS).xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
<integer>2</integer>
</dict>
<key>FeelsWidgetExtension.xcscheme_^#shared#^_</key>
<dict>

View File

@@ -7,12 +7,17 @@
import SwiftUI
import CloudKitSyncMonitor
import UniformTypeIdentifiers
struct SettingsView: View {
@Environment(\.dismiss) var dismiss
@State private var showOnboarding = false
@State private var showingExporter = false
@State private var showingImporter = false
@State private var importContent = ""
@State private var showOnboarding = false
@State private var showSpecialThanks = false
@State private var showWhyBGMode = false
@ObservedObject var syncMonitor = SyncMonitor.shared
@@ -44,6 +49,9 @@ struct SettingsView: View {
if useCloudKit {
cloudKitStatus
}
exportData
importData
}
Spacer()
@@ -62,6 +70,57 @@ struct SettingsView: View {
theme.currentTheme.bg
.edgesIgnoringSafeArea(.all)
)
.fileExporter(isPresented: $showingExporter,
documents: [
TextFile()
],
contentType: .plainText,
onCompletion: { result in
switch result {
case .success(let url):
print("Saved to \(url)")
case .failure(let error):
print(error.localizedDescription)
}
})
.fileImporter(isPresented: $showingImporter, allowedContentTypes: [.text],
allowsMultipleSelection: false) { result in
do {
guard let selectedFile: URL = try result.get().first else { return }
if selectedFile.startAccessingSecurityScopedResource() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss +0000"
guard let input = String(data: try Data(contentsOf: selectedFile), encoding: .utf8) else { return }
defer { selectedFile.stopAccessingSecurityScopedResource() }
var rows = input.components(separatedBy: "\n")
rows.removeFirst()
for row in rows {
let columns = row.components(separatedBy: ",")
if columns.count != 7 {
continue
}
let moodEntry = MoodEntry(context: PersistenceController.shared.viewContext)
moodEntry.canDelete = Bool(columns[0])!
moodEntry.canEdit = Bool(columns[1])!
moodEntry.entryType = Int16(columns[2])!
moodEntry.forDate = dateFormatter.date(from: columns[3])
moodEntry.moodValue = Int16(columns[4])!
moodEntry.timestamp = dateFormatter.date(from: columns[5])
moodEntry.weekDay = Int16(columns[6])!
try! PersistenceController.shared.viewContext.save()
}
PersistenceController.shared.saveAndRunDataListerners()
} else {
// Handle denied access
}
} catch {
// Handle failure.
print("Unable to read file contents")
print(error.localizedDescription)
}
}
}
private var closeButtonView: some View {
@@ -222,6 +281,34 @@ struct SettingsView: View {
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var exportData: some View {
ZStack {
theme.currentTheme.secondaryBGColor
Button(action: {
showingExporter.toggle()
}, label: {
Text("Export")
})
.padding()
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var importData: some View {
ZStack {
theme.currentTheme.secondaryBGColor
Button(action: {
showingImporter.toggle()
}, label: {
Text("Import")
})
.padding()
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var randomIcons: some View {
ZStack {
theme.currentTheme.secondaryBGColor
@@ -354,6 +441,50 @@ struct SettingsView: View {
}
}
struct TextFile: FileDocument {
// tell the system we support only plain text
static var readableContentTypes = [UTType.plainText]
// by default our document is empty
var text = ""
// a simple initializer that creates new, empty documents
init() {
let entries = PersistenceController.shared.getData(startDate: Date(timeIntervalSince1970: 0),
endDate: Date(),
includedDays: [])
var csvString = "canDelete,canEdit,entryType,forDate,moodValue,timestamp,weekDay\n"
for entry in entries {
let canDelete = entry.canDelete
let canEdit = entry.canEdit
let entryType = entry.entryType
let forDate = entry.forDate!
let moodValue = entry.moodValue
let timestamp = entry.timestamp!
let weekDay = entry.weekDay
let dataString = "\(canDelete),\(canEdit),\(entryType),\(String(describing: forDate)),\(moodValue),\(String(describing:timestamp)),\(weekDay)\n"
print("DATA: \(dataString)")
csvString = csvString.appending(dataString)
}
text = csvString
}
// this initializer loads data that has been saved previously
init(configuration: ReadConfiguration) throws {
if let data = configuration.file.regularFileContents {
text = String(decoding: data, as: UTF8.self)
}
}
// this will be called when the system wants to write our data to disk
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let data = Data(text.utf8)
return FileWrapper(regularFileWithContents: data)
}
}
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
SettingsView()