Skip to content

Commit

Permalink
Merge pull request #2 from aapis/backup
Browse files Browse the repository at this point in the history
Backup note
  • Loading branch information
aapis authored Nov 16, 2020
2 parents d173b47 + 934e125 commit 6bb472f
Show file tree
Hide file tree
Showing 17 changed files with 577 additions and 4 deletions.
8 changes: 6 additions & 2 deletions DLPrototype.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
5309EE3D25619A6D00B3BC06 /* Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5309EE3C25619A6D00B3BC06 /* Backup.swift */; };
53218D4824B7F6EB0088ABE9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53218D4724B7F6EB0088ABE9 /* AppDelegate.swift */; };
53218D4A24B7F6EB0088ABE9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53218D4924B7F6EB0088ABE9 /* ContentView.swift */; };
53218D4D24B7F6EB0088ABE9 /* DLPrototype.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 53218D4B24B7F6EB0088ABE9 /* DLPrototype.xcdatamodeld */; };
Expand Down Expand Up @@ -39,6 +40,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
5309EE3C25619A6D00B3BC06 /* Backup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backup.swift; sourceTree = "<group>"; };
53218D4424B7F6EB0088ABE9 /* DLPrototype.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLPrototype.app; sourceTree = BUILT_PRODUCTS_DIR; };
53218D4724B7F6EB0088ABE9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
53218D4924B7F6EB0088ABE9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -156,6 +158,7 @@
537368CC24B93D6A00193E88 /* Search.swift */,
537368CE24B93D9300193E88 /* Log.swift */,
537368D024B93DB600193E88 /* Add.swift */,
5309EE3C25619A6D00B3BC06 /* Backup.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -293,6 +296,7 @@
buildActionMask = 2147483647;
files = (
53218D4A24B7F6EB0088ABE9 /* ContentView.swift in Sources */,
5309EE3D25619A6D00B3BC06 /* Backup.swift in Sources */,
537368CD24B93D6A00193E88 /* Search.swift in Sources */,
537368CF24B93D9300193E88 /* Log.swift in Sources */,
537368D124B93DB600193E88 /* Add.swift in Sources */,
Expand Down Expand Up @@ -464,7 +468,7 @@
CODE_SIGN_ENTITLEMENTS = DLPrototype/DLPrototype.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 8;
CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_ASSET_PATHS = "\"DLPrototype/Preview Content\"";
DEVELOPMENT_TEAM = 6DT7L2N5X6;
ENABLE_HARDENED_RUNTIME = YES;
Expand All @@ -488,7 +492,7 @@
CODE_SIGN_ENTITLEMENTS = DLPrototype/DLPrototype.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 8;
CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_ASSET_PATHS = "\"DLPrototype/Preview Content\"";
DEVELOPMENT_TEAM = 6DT7L2N5X6;
ENABLE_HARDENED_RUNTIME = YES;
Expand Down
97 changes: 97 additions & 0 deletions DLPrototype/Views/Backup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// Log.swift
// DLPrototype
//
// Created by Ryan Priebe on 2020-07-10.
// Copyright © 2020 YegCollective. All rights reserved.
//

import SwiftUI

struct Backup: View {
@State private var lastBackupDate: String = ""

var category: Category

var body: some View {
VStack(alignment: .leading) {
HStack {
Text(Image(systemName: "cloud.fill"))
.font(.title)
Text("Backup \(category.title).log")
.font(.title)
}

Divider()

Text("Last Backup: ") + Text($lastBackupDate.wrappedValue)

Button("Backup Now", action: {
self.performBackup()
})
.background(Color.accentColor)

Spacer()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.padding()
.onAppear(perform: getLastBackupDate)
}

private func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask)

return paths[0]
}

private func getLastBackupDate() -> Void {
let log = getDocumentsDirectory().appendingPathComponent("\(category.title).log")

if let logLines = try? String(contentsOf: log) {
let lines = logLines.components(separatedBy: .newlines)

if lines.count > 0 {
$lastBackupDate.wrappedValue = lines.first!
}
}
}

private func performBackup() -> Void {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm"

let date = formatter.string(from: Date())
let to = getDocumentsDirectory().appendingPathComponent("Log Backups/\(category.title)-\(date).log")
let at = getDocumentsDirectory().appendingPathComponent("\(category.title).log")

if let _ = try? FileManager().copyItem(at: at, to: to) {
let text = "Backed up to \"Log Backups/\(date)\""

logLine(text: text)

$lastBackupDate.wrappedValue = date
}
}

private func writeToLog(output: Data) -> Void {
let fileName = "\(category.title).log"
let filePath = getDocumentsDirectory().appendingPathComponent(fileName)

if let fileHandle = try? FileHandle(forWritingTo: filePath) {
fileHandle.truncateFile(atOffset: 0)
fileHandle.write(output)
fileHandle.closeFile()
}
}

private func logLine(text: String) -> Void {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm"

let date = formatter.string(from: Date())

guard let line: Data = ("\n\(date) - \(text)").data(using: String.Encoding.utf8) else { return }

writeToLog(output: line)
}
}
9 changes: 7 additions & 2 deletions DLPrototype/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,18 @@ struct ContentView: View {
.padding(10)
}

NavigationLink(destination: Search(category: category)) {
Text("Search")
.padding(10)
}

NavigationLink(destination: Log(category: category)) {
Text("View")
.padding(10)
}

NavigationLink(destination: Search(category: category)) {
Text("Search")
NavigationLink(destination: Backup(category: category)) {
Text("Backup")
.padding(10)
}
}
Expand Down
11 changes: 11 additions & 0 deletions DLPrototypeiOS/Assets.xcassets/AccentColor.colorset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
98 changes: 98 additions & 0 deletions DLPrototypeiOS/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions DLPrototypeiOS/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
81 changes: 81 additions & 0 deletions DLPrototypeiOS/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// ContentView.swift
// DLPrototypeiOS
//
// Created by Ryan Priebe on 2020-11-14.
// Copyright © 2020 YegCollective. All rights reserved.
//

import SwiftUI
import CoreData

struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext

@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
animation: .default)
private var items: FetchedResults<Item>

var body: some View {
List {
ForEach(items) { item in
Text("Item at \(item.timestamp!, formatter: itemFormatter)")
}
.onDelete(perform: deleteItems)
}
.toolbar {
#if os(iOS)
EditButton()
#endif

Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}

private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.timestamp = Date()

do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}

private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(viewContext.delete)

do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}

private let itemFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .medium
return formatter
}()

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
8 changes: 8 additions & 0 deletions DLPrototypeiOS/DLPrototypeiOS.xcdatamodeld/.xccurrentversion
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>DLPrototypeiOS.xcdatamodel</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="true" userDefinedModelVersionIdentifier="">
<entity name="Item" representedClassName="Item" syncable="YES" codeGenerationType="class">
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
</entity>
<elements>
<element name="Item" positionX="-63" positionY="-18" width="128" height="44"/>
</elements>
</model>
Loading

0 comments on commit 6bb472f

Please sign in to comment.