commit c1f41d865762e0842dff632839538e63705b3fa6 Author: FIGBERT <figbert@figbert.com> Date: Wed, 12 Aug 2020 13:39:01 -0700 Rewrite txtodo in new cross-platform structure Diffstat:
A | .gitattributes | | | 1 | + |
A | .gitignore | | | 10 | ++++++++++ |
A | README.md | | | 44 | ++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/AddNoteView.swift | | | 95 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/AddTask.swift | | | 145 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/Assets.xcassets/AccentColor.colorset/Contents.json | | | 11 | +++++++++++ |
A | Shared/Assets.xcassets/AppIcon.appiconset/Contents.json | | | 148 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/Assets.xcassets/Contents.json | | | 6 | ++++++ |
A | Shared/ContentView.swift | | | 102 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/Data Models/Task+CoreDataClass.swift | | | 15 | +++++++++++++++ |
A | Shared/Data Models/Task+CoreDataProperties.swift | | | 32 | ++++++++++++++++++++++++++++++++ |
A | Shared/Data Models/txtodo.xcdatamodeld/txtodo.xcdatamodel/contents | | | 17 | +++++++++++++++++ |
A | Shared/DevicePaddingModifiers.swift | | | 31 | +++++++++++++++++++++++++++++++ |
A | Shared/FrameModifier.swift | | | 18 | ++++++++++++++++++ |
A | Shared/NoteView.swift | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/SectionLabel.swift | | | 29 | +++++++++++++++++++++++++++++ |
A | Shared/Settings Views/NotificationSection.swift | | | 89 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Shared/en.lproj/Localizable.strings | | | 0 | |
A | Shared/he.lproj/Localizable.strings | | | 0 | |
A | Shared/txtodoApp.swift | | | 62 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | iOS/AboutSheet.swift | | | 36 | ++++++++++++++++++++++++++++++++++++ |
A | iOS/HomeHeaderView.swift | | | 25 | +++++++++++++++++++++++++ |
A | iOS/Info.plist | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | iOS/MenuView.swift | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | iOS/NoteSheet.swift | | | 28 | ++++++++++++++++++++++++++++ |
A | iOS/SettingsSheet.swift | | | 28 | ++++++++++++++++++++++++++++ |
A | iOS/TaskView.swift | | | 143 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | macOS/HomeHeaderView.swift | | | 26 | ++++++++++++++++++++++++++ |
A | macOS/Info.plist | | | 28 | ++++++++++++++++++++++++++++ |
A | macOS/SettingsView.swift | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
A | macOS/TaskView.swift | | | 156 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | macOS/macOS.entitlements | | | 22 | ++++++++++++++++++++++ |
A | txtodo.entitlements | | | 16 | ++++++++++++++++ |
A | txtodo.xcodeproj/project.pbxproj | | | 611 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | txtodo.xcodeproj/project.xcworkspace/contents.xcworkspacedata | | | 7 | +++++++ |
A | txtodo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist | | | 8 | ++++++++ |
36 files changed, 2215 insertions(+), 0 deletions(-)
diff --git a/.gitattributes b/.gitattributes @@ -0,0 +1 @@ +** !text !filter !merge !diff diff --git a/.gitignore b/.gitignore @@ -0,0 +1,10 @@ +# File generated based on GitHub gitignore Swift.gitignore recommendations +xcuserdata/ +*.ipa +*.dSYM.zip +*.dSYM +*.hmap +timeline.xctimeline +playground.xcworkspace +.build/ +.DS_Store diff --git a/README.md b/README.md @@ -0,0 +1,44 @@ +# txtodo + +pronounced "text to do," **txtodo** is a minimalist open-source todo list app made by [figbert][0] and inspired by [jeff huang][1]. it lists your immediate, short-term tasks to help you get things done without overthinking it. plus, it's lightweight, open-source, and built with swiftui. + +after reading a [post][2] by jeff huang on [hacker news][3], i started thinking about how i managed my own daily tasks. i wanted to make a solution that could train me into being highly productive. + +that solution is **txtodo**. it manages immediate, short-term tasks to help you get things done. welcome to productivity. welcome to txtodo. + +download it on [the app store](https://apps.apple.com/us/app/txtodo/id1504609185) and give it a try! + +## milestones +- [x] launch alpha on testflight +- [x] launch wider beta testing +- [x] submit to apple for approval +- [x] go live on the app store! :tada: + +## short term goals +- [x] implement a "floating" task system for long term goals +- [ ] add i18n + - [x] hebrew + - [ ] arabic + - [ ] chinese + - [ ] spanish + - [ ] japanese + +## long term goals +- [x] add e2e encrypted cloud storage +- [x] create macos companion app +- [x] monetize in a not-evil way + +# links +1. [txtodo homepage](https://txtodo.app/) +2. [figbert homepage](https://figbert.com/) +3. [txtodo repository](https://github.com/therealFIGBERT/txtodo) +4. [txtodo homepage repository](https://github.com/therealFIGBERT/txtodo.app) +5. [txtodo on the App Store](https://apps.apple.com/us/app/txtodo/id1504609185) + +# license +copyright © 2020 figbert industries. all rights reserved. + +[0]: https://figbert.com/ +[1]: https://jeffhuang.com/productivity_text_file/ +[2]: https://news.ycombinator.com/item?id=22276184 +[3]: https://news.ycombinator.com/ diff --git a/Shared/AddNoteView.swift b/Shared/AddNoteView.swift @@ -0,0 +1,95 @@ +// +// AddNoteView.swift +// txtodo +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI + +struct AddNoteView: View { + @Environment(\.managedObjectContext) var managedObjectContext + @ObservedObject var task: Task + @State private var config = AddNoteViewConfig() + + var body: some View { + Group { + if !config.addingNote { + HStack { + Image(systemName: "plus.square") + Spacer() + Text("create a note") + Spacer() + Image(systemName: "plus.square") + } + .onTapGesture { + #if os(iOS) + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + self.config.addingNote = true + generator.impactOccurred() + #else + self.config.addingNote = true + #endif + } + } else { + HStack { + Image(systemName: "multiply.square") + .onTapGesture { + #if os(iOS) + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + config.clear() + generator.impactOccurred() + #else + config.clear() + #endif + } + Spacer() + TextField("tap", text: $config.newNoteText) { + addTask() + } + .multilineTextAlignment(.center) + Spacer() + Image(systemName: "plus.square") + .onTapGesture { + addTask(forceKeyboardClose: true) + } + } + } + } + .font(.system(size: 18, weight: .light, design: .rounded)) + .foregroundColor(Color.secondary.opacity(0.5)) + .multilineTextAlignment(.center) + } + + func addTask(forceKeyboardClose: Bool = false) { + #if os(iOS) + if forceKeyboardClose { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } + #endif + guard self.config.newNoteText != "" else {return} + #if os(iOS) + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + #endif + self.managedObjectContext.performAndWait { + self.task.notes.append(self.config.newNoteText) + try? self.managedObjectContext.save() + } + #if os(iOS) + generator.impactOccurred() + #endif + self.config.clear() + } +} + +struct AddNoteViewConfig { + var addingNote: Bool = false + var newNoteText: String = "" + + mutating func clear() { + addingNote = false + newNoteText = "" + } +} diff --git a/Shared/AddTask.swift b/Shared/AddTask.swift @@ -0,0 +1,145 @@ +// +// AddTask.swift +// txtodo +// +// Created by FIGBERT on 8/3/20. +// + +import SwiftUI + +struct AddTaskController: View { + @Environment(\.managedObjectContext) var managedObjectContext + @State private var config = AddTaskControllerConfig() + let lessThanThreeFloatingTasks: Bool + + var body: some View { + HStack { + if config.showingDaily { + AddTaskView(showingOtherAddTaskView: $config.showingFloating, isAddingDailyTask: true) + .environment(\.managedObjectContext, self.managedObjectContext) + } + if config.showingDaily && lessThanThreeFloatingTasks && config.showingFloating { + Spacer() + } + if lessThanThreeFloatingTasks && config.showingFloating { + AddTaskView(showingOtherAddTaskView: $config.showingDaily, isAddingDailyTask: false) + .environment(\.managedObjectContext, self.managedObjectContext) + } + } + .horizontalPaddingOnMacOS() + } +} + +struct AddTaskView: View { + @Environment(\.managedObjectContext) var managedObjectContext + @State private var config = AddTaskViewConfig() + @Binding var showingOtherAddTaskView: Bool + let isAddingDailyTask: Bool + + var body: some View { + Group { + if !config.addingTask { + HStack { + Image(systemName: "plus.square") + Spacer() + Text(isAddingDailyTask ? NSLocalizedString("daily", comment: "") : NSLocalizedString("floating", comment: "")) + Spacer() + Image(systemName: "plus.square") + } + .onTapGesture { + #if os(iOS) + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + self.config.addingTask = true + self.showingOtherAddTaskView = false + generator.impactOccurred() + #else + self.config.addingTask = true + self.showingOtherAddTaskView = false + #endif + } + } else { + HStack { + Image(systemName: "multiply.square") + .onTapGesture { + #if os(iOS) + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + config.clear() + self.showingOtherAddTaskView = true + generator.impactOccurred() + #else + config.clear() + self.showingOtherAddTaskView = true + #endif + } + Spacer() + TextField("tap", text: $config.newTaskText) { + addTask() + } + .multilineTextAlignment(.center) + Picker( + selection: $config.newTaskPriority, + label: Text("task priority"), + content: { + Text("!").tag(1) + Text("!!").tag(2) + Text("!!!").tag(3) + }) + .pickerStyle(SegmentedPickerStyle()) + .labelsHidden() + Spacer() + Image(systemName: "plus.square") + .onTapGesture { + addTask(forceKeyboardClose: true) + } + } + } + } + .font(.system(size: 18, weight: .light, design: .rounded)) + .foregroundColor(Color.secondary.opacity(0.5)) + .multilineTextAlignment(.center) + } + + func addTask(forceKeyboardClose: Bool = false) { + #if os(iOS) + if forceKeyboardClose { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } + #endif + guard self.config.newTaskText != "" else {return} + #if os(iOS) + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + #endif + let newTask = Task(context: self.managedObjectContext) + newTask.id = UUID() + newTask.date = Date() + newTask.notes = [String]() + newTask.daily = self.isAddingDailyTask + newTask.name = self.config.newTaskText + newTask.priority = Int16(self.config.newTaskPriority) + try? self.managedObjectContext.save() + #if os(iOS) + generator.impactOccurred() + #endif + self.config.clear() + self.showingOtherAddTaskView = true + } +} + +struct AddTaskControllerConfig { + var showingDaily: Bool = true + var showingFloating: Bool = true +} + +struct AddTaskViewConfig { + var addingTask: Bool = false + var newTaskText: String = "" + var newTaskPriority: Int = 1 + + mutating func clear() { + addingTask = false + newTaskText = "" + newTaskPriority = 1 + } +} diff --git a/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/Shared/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json b/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,148 @@ +{ + "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" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Shared/Assets.xcassets/Contents.json b/Shared/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Shared/ContentView.swift b/Shared/ContentView.swift @@ -0,0 +1,102 @@ +// +// ContentView.swift +// Shared +// +// Created by FIGBERT on 7/27/20. +// + +import SwiftUI + +struct ContentView: View { + @Environment(\.managedObjectContext) var managedObjectContext + @FetchRequest( + entity: Task.entity(), + sortDescriptors: [ + NSSortDescriptor(keyPath: \Task.completed, ascending: true), + NSSortDescriptor(keyPath: \Task.priority, ascending: false), + NSSortDescriptor(keyPath: \Task.name, ascending: true) + ], + predicate: NSPredicate(format: "daily == %d", false) + ) var floatingTasks: FetchedResults<Task> + @FetchRequest( + entity: Task.entity(), + sortDescriptors: [ + NSSortDescriptor(keyPath: \Task.completed, ascending: true), + NSSortDescriptor(keyPath: \Task.priority, ascending: false), + NSSortDescriptor(keyPath: \Task.name, ascending: true) + ], + predicate: NSPredicate( + format: "daily == %d AND date < %@", + argumentArray: [ + true, + Calendar.current.startOfDay( + for: Calendar.current.date( + byAdding: .day, + value: 1, + to: Date() + )! + ) + ] + ) + ) var dailyTasks: FetchedResults<Task> + let currentDay = Calendar.current.component(.day, from: Date.init()) + + var body: some View { + ZStack(alignment: .bottomTrailing) { + #if os(iOS) + Color.gray.opacity(0.25) + .edgesIgnoringSafeArea(.all) + #endif + ScrollView(.vertical, showsIndicators: false) { + VStack(alignment: .leading, spacing: 10) { + HomeHeaderView().padding(.top) + if floatingTasks.count > 0 { + SectionLabel(text: "floating") + ForEach(self.floatingTasks, id: \.id) { task in + TaskView(task: task, priority: Int(task.priority)) + .environment(\.managedObjectContext, self.managedObjectContext) + .onAppear(perform: { + if task.completed && Calendar.current.component(.day, from: task.date) < self.currentDay { + self.managedObjectContext.performAndWait { + self.managedObjectContext.delete(task) + try? self.managedObjectContext.save() + } + } + }) + } + } + if dailyTasks.count > 0 { + SectionLabel(text: "daily") + ForEach(self.dailyTasks, id: \.id) { task in + TaskView(task: task, priority: Int(task.priority)) + .environment(\.managedObjectContext, self.managedObjectContext) + .onAppear(perform: { + if Calendar.current.component(.day, from: task.date) < self.currentDay { + self.managedObjectContext.performAndWait { + self.managedObjectContext.delete(task) + try? self.managedObjectContext.save() + } + } + }) + } + } + AddTaskController(lessThanThreeFloatingTasks: floatingTasks.count < 3) + .environment(\.managedObjectContext, self.managedObjectContext) + Spacer() + } + .horizontalPaddingOnIOS() + .animation(.easeIn(duration: 0.15)) + } + #if os(iOS) + MenuView() + #endif + } + .modifier(FrameModifier()) + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/Shared/Data Models/Task+CoreDataClass.swift b/Shared/Data Models/Task+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// Task+CoreDataClass.swift +// txtodo +// +// Created by FIGBERT on 7/27/20. +// +// + +import Foundation +import CoreData + +@objc(Task) +public class Task: NSManagedObject { + +} diff --git a/Shared/Data Models/Task+CoreDataProperties.swift b/Shared/Data Models/Task+CoreDataProperties.swift @@ -0,0 +1,32 @@ +// +// Task+CoreDataProperties.swift +// txtodo +// +// Created by FIGBERT on 7/31/20. +// +// + +import Foundation +import CoreData + + +extension Task { + + @nonobjc public class func fetchRequest() -> NSFetchRequest<Task> { + return NSFetchRequest<Task>(entityName: "Task") + } + + @NSManaged public var completed: Bool + @NSManaged public var daily: Bool + @NSManaged public var date: Date + @NSManaged public var id: UUID + @NSManaged public var name: String + @NSManaged public var notes: [String] + @NSManaged public var priority: Int16 + @NSManaged public var hasBeenDelayed: Bool + +} + +extension Task : Identifiable { + +} diff --git a/Shared/Data Models/txtodo.xcdatamodeld/txtodo.xcdatamodel/contents b/Shared/Data Models/txtodo.xcdatamodeld/txtodo.xcdatamodel/contents @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17175" systemVersion="20A5323l" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier=""> + <entity name="Task" representedClassName="Task" syncable="YES"> + <attribute name="completed" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="daily" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/> + <attribute name="date" attributeType="Date" defaultDateTimeInterval="599601600" usesScalarValueType="NO"/> + <attribute name="hasBeenDelayed" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> + <attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/> + <attribute name="name" attributeType="String" defaultValueString=""/> + <attribute name="notes" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromDataTransformerName"/> + <attribute name="priority" attributeType="Integer 16" defaultValueString="1" usesScalarValueType="YES"/> + </entity> + <elements> + <element name="Task" positionX="-63" positionY="-18" width="128" height="149"/> + </elements> +</model> +\ No newline at end of file diff --git a/Shared/DevicePaddingModifiers.swift b/Shared/DevicePaddingModifiers.swift @@ -0,0 +1,31 @@ +// +// DevicePaddingModifiers.swift +// txtodo +// +// Created by FIGBERT on 8/11/20. +// + +import SwiftUI + +struct HorizontalPadding: ViewModifier { + func body(content: Content) -> some View { + return content.padding(.horizontal) + } +} + +extension View { + func horizontalPaddingOnIOS() -> some View { + #if os(iOS) + return self.modifier(HorizontalPadding()) + #else + return self + #endif + } + func horizontalPaddingOnMacOS() -> some View { + #if os(macOS) + return self.modifier(HorizontalPadding()) + #else + return self + #endif + } +} diff --git a/Shared/FrameModifier.swift b/Shared/FrameModifier.swift @@ -0,0 +1,18 @@ +// +// FrameModifier.swift +// txtodo +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI + +struct FrameModifier: ViewModifier { + func body(content: Content) -> some View { + #if os(macOS) + return content.frame(width: 325, height: 400) + #else + return content + #endif + } +} diff --git a/Shared/NoteView.swift b/Shared/NoteView.swift @@ -0,0 +1,78 @@ +// +// NoteView.swift +// txtodo +// +// Created by FIGBERT on 8/11/20. +// + +import SwiftUI + +struct NoteView: View { + @Environment(\.managedObjectContext) var managedObjectContext + @ObservedObject var task: Task + @State var note: String + @State private var config = NoteViewConfig() + + var body: some View { + let noteIntermediary = Binding<String>( + get: { self.note }, + set: { value in + self.config.editingCache = value + } + ) + return HStack { + Image(systemName: "minus") + .padding(.trailing) + if !config.editing { + Text(note) + .onTapGesture(count: 2) { + self.config.editing = true + } + } else { + TextField("edit note", text: noteIntermediary) { + if let index = self.task.notes.firstIndex(of: self.note) { + self.managedObjectContext.performAndWait { + self.task.notes[index] = self.config.editingCache + try? self.managedObjectContext.save() + } + } + self.config.editing = false + } + } + Spacer() + if config.showingDelete { + Image(systemName: "trash.circle.fill") + .font(.system(size: 25)) + .foregroundColor(.red) + .onTapGesture { + if let index = self.task.notes.firstIndex(of: self.note) { + self.managedObjectContext.performAndWait { + self.task.notes.remove(at: index) + try? self.managedObjectContext.save() + } + } + } + } + } + .offset(x: config.offset) + .gesture( + DragGesture() + .onChanged({ value in + config.offset = value.translation.width + }) + .onEnded({ value in + if -config.offset > 15 { + config.showingDelete.toggle() + } + config.offset = 0 + }) + ) + } +} + +struct NoteViewConfig { + var editing: Bool = false + var showingDelete: Bool = false + var offset: CGFloat = 0 + var editingCache = "" +} diff --git a/Shared/SectionLabel.swift b/Shared/SectionLabel.swift @@ -0,0 +1,29 @@ +// +// SectionLabel.swift +// txtodo +// +// Created by FIGBERT on 7/28/20. +// + +import SwiftUI + +struct SectionLabel: View { + let text: String + + var body: some View { + HStack { + Text(NSLocalizedString(text, comment: "")) + .font(.system(size: 10, weight: .bold)) + .foregroundColor(.gray) + .multilineTextAlignment(.leading) + Spacer() + } + .horizontalPaddingOnMacOS() + } +} + +struct SectionLabel_Previews: PreviewProvider { + static var previews: some View { + SectionLabel(text: "example") + } +} diff --git a/Shared/Settings Views/NotificationSection.swift b/Shared/Settings Views/NotificationSection.swift @@ -0,0 +1,89 @@ +// +// NotificationSection.swift +// txtodo +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI +import UserNotifications + +struct NotificationSection: View { + @AppStorage("notifications") var notificationsEnabled: Bool = false { willSet { + if !newValue { + UNUserNotificationCenter.current().removeAllPendingNotificationRequests() + } else { + enableNotifications() + } + } } + @AppStorage("notificationID") var notificationID: String = "unset" + @AppStorage("notificationTime") var notificationTime: Int = 0 { willSet { enableNotifications() } } + + var body: some View { + Section { + Toggle(isOn: $notificationsEnabled) { + #if os(iOS) + Label(notificationsEnabled ? "notifications enabled" : "notifications disabled", systemImage: "app.badge") + #else + Text("txtodo notifications \(notificationsEnabled ? "enabled" : "disabled")") + #endif + } + HStack { + Label("time scheduled", systemImage: "clock") + Spacer() + Picker( + selection: $notificationTime, + label: Text("notification time"), + content: { + Text("8:30").tag(0) + Text("9:30").tag(1) + Text("10:30").tag(2) + }) + .labelsHidden() + .disabled(!notificationsEnabled) + .pickerStyle(SegmentedPickerStyle()) + } + } + } + + func enableNotifications() { + UNUserNotificationCenter.current().removeAllPendingNotificationRequests() + UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { success, error in + if success { + let content = UNMutableNotificationContent() + content.title = String(format: NSLocalizedString("open txtodo", comment: "")) + content.body = String(format: NSLocalizedString("take some time to plan your day", comment: "")) + content.sound = UNNotificationSound.default + var time = DateComponents() + if self.notificationTime == 0 { + time.hour = 8 + } else if self.notificationTime == 1 { + time.hour = 9 + } else { + time.hour = 10 + } + time.minute = 30 + let trigger = UNCalendarNotificationTrigger( + dateMatching: time, + repeats: true + ) + let id = UUID().uuidString + self.notificationID = id + let request = UNNotificationRequest( + identifier: id, + content: content, + trigger: trigger + ) + UNUserNotificationCenter.current().add(request) + } else if let error = error { + print(error.localizedDescription) + } + } + } +} + +struct NotificationSection_Previews: PreviewProvider { + static var previews: some View { + NotificationSection() + } +} diff --git a/Shared/en.lproj/Localizable.strings b/Shared/en.lproj/Localizable.strings Binary files differ. diff --git a/Shared/he.lproj/Localizable.strings b/Shared/he.lproj/Localizable.strings Binary files differ. diff --git a/Shared/txtodoApp.swift b/Shared/txtodoApp.swift @@ -0,0 +1,62 @@ +// +// txtodoApp.swift +// Shared +// +// Created by FIGBERT on 7/27/20. +// + +import SwiftUI +import CoreData +import UserNotifications + +@main +struct txtodoApp: App { + @Environment(\.scenePhase) private var scenePhase + + @SceneBuilder var body: some Scene { + WindowGroup { + ContentView() + .environment(\.managedObjectContext, self.persistentContainer.viewContext) + } + .onChange(of: scenePhase) { phase in + switch phase { + case .active: + UNUserNotificationCenter.current().removeAllDeliveredNotifications() + case .inactive: + saveContext() + case .background: + saveContext() + @unknown default: + saveContext() + } + } + #if os(macOS) + Settings { + SettingsView() + } + #endif + } + + var persistentContainer: NSPersistentCloudKitContainer = { + let container = NSPersistentCloudKitContainer(name: "txtodo") + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error as NSError? { + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy + container.viewContext.automaticallyMergesChangesFromParent = true + return container + }() + func saveContext() { + let context = persistentContainer.viewContext + if context.hasChanges { + do { + try context.save() + } catch { + let nserror = error as NSError + fatalError("Unresolved error \(nserror), \(nserror.userInfo)") + } + } + } +} diff --git a/iOS/AboutSheet.swift b/iOS/AboutSheet.swift @@ -0,0 +1,36 @@ +// +// AboutSheet.swift +// txtodo (iOS) +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI + +struct AboutSheet: View { + var body: some View { + VStack() { + Text("about") + .underline() + .padding(.vertical) + Text("aboutOne") + .multilineTextAlignment(.center) + Text("aboutTwo") + .multilineTextAlignment(.center) + .padding(.vertical) + Text("aboutThree") + .multilineTextAlignment(.center) + Link(destination: URL(string: "https://txtodo.app/")!) { Text("view site") } + .padding(.vertical) + Link(destination: URL(string: "https://jeffhuang.com/productivity_text_file/")!) { Text("view inspo") } + Spacer() + } + .padding() + } +} + +struct AboutSheet_Previews: PreviewProvider { + static var previews: some View { + AboutSheet() + } +} diff --git a/iOS/HomeHeaderView.swift b/iOS/HomeHeaderView.swift @@ -0,0 +1,25 @@ +// +// HomeHeaderView.swift +// txtodo (iOS) +// +// Created by FIGBERT on 8/9/20. +// + +import SwiftUI + +struct HomeHeaderView: View { + var body: some View { + HStack { + Spacer() + Text("title") + .underline() + Spacer() + } + } +} + +struct HomeHeaderView_Previews: PreviewProvider { + static var previews: some View { + HomeHeaderView() + } +} diff --git a/iOS/Info.plist b/iOS/Info.plist @@ -0,0 +1,55 @@ +<?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>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> + <key>CFBundleShortVersionString</key> + <string>3.0.0</string> + <key>CFBundleVersion</key> + <string>3.0.0</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>UIApplicationSceneManifest</key> + <dict> + <key>UIApplicationSupportsMultipleScenes</key> + <true/> + </dict> + <key>UIApplicationSupportsIndirectInputEvents</key> + <true/> + <key>UIBackgroundModes</key> + <array> + <string>remote-notification</string> + </array> + <key>UILaunchScreen</key> + <dict/> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/iOS/MenuView.swift b/iOS/MenuView.swift @@ -0,0 +1,55 @@ +// +// MenuView.swift +// txtodo (iOS) +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI + +struct MenuView: View { + @State private var config = MenuViewConfig() + + var body: some View { + HStack { + VStack(alignment: .leading, spacing: 18) { + if config.active { + Label("settings", systemImage: "gear") + .onTapGesture { + config.showSettings = true + } + .sheet(isPresented: $config.showSettings) { + SettingsSheet() + } + Label("about", systemImage: "book") + .onTapGesture { + config.showAbout = true + } + .sheet(isPresented: $config.showAbout) { + AboutSheet() + } + } + Image(systemName: config.active ? "chevron.up" : "line.horizontal.3") + .font(.system(size: 30, weight: .ultraLight)) + .onTapGesture { + config.active.toggle() + } + } + Spacer() + } + .font(.system(size: 18, weight: .light)) + .padding() + } +} + +struct MenuViewConfig { + var active: Bool = false + var showSettings: Bool = false + var showAbout: Bool = false +} + +struct MenuView_Previews: PreviewProvider { + static var previews: some View { + MenuView() + } +} diff --git a/iOS/NoteSheet.swift b/iOS/NoteSheet.swift @@ -0,0 +1,28 @@ +// +// NoteSheet.swift +// txtodo +// +// Created by FIGBERT on 8/5/20. +// + +import SwiftUI + +struct NoteSheet: View { + @Environment(\.managedObjectContext) var managedObjectContext + @ObservedObject var task: Task + + var body: some View { + ScrollView(.vertical, showsIndicators: false) { + VStack(spacing: 10) { + Text(task.name) + .underline() + ForEach(task.notes, id: \.self) { note in + NoteView(task: task, note: note) + .environment(\.managedObjectContext, self.managedObjectContext) + } + AddNoteView(task: task) + } + } + .padding() + } +} diff --git a/iOS/SettingsSheet.swift b/iOS/SettingsSheet.swift @@ -0,0 +1,28 @@ +// +// SettingsSheet.swift +// txtodo (iOS) +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI + +struct SettingsSheet: View { + var body: some View { + VStack { + Text("settings") + .underline() + .padding() + Form { + NotificationSection() + } + .listStyle(GroupedListStyle()) + } + } +} + +struct SettingsSheet_Previews: PreviewProvider { + static var previews: some View { + SettingsSheet() + } +} diff --git a/iOS/TaskView.swift b/iOS/TaskView.swift @@ -0,0 +1,143 @@ +// +// TaskView.swift +// txtodo +// +// Created by FIGBERT on 7/27/20. +// + +import SwiftUI + +struct TaskView: View { + @Environment(\.managedObjectContext) var managedObjectContext + @Environment(\.layoutDirection) var direction + @ObservedObject var task: Task + @State var priority: Int + @State private var config = TaskViewConfig() + + var body: some View { + let priorityIntermediary = Binding<Int>( + get: { self.priority }, + set: { value in + self.priority = value + self.managedObjectContext.performAndWait { + self.task.priority = Int16(value) + try? self.managedObjectContext.save() + } + self.config.editingPriority = false + } + ) + return HStack { + if task.daily && !task.hasBeenDelayed && !task.completed && config.showingDelay { + Image(systemName: "calendar.circle.fill") + .font(.system(size: 25)) + .foregroundColor(.blue) + .onTapGesture { + self.managedObjectContext.performAndWait { + self.task.date = Calendar.current.date(byAdding: .day, value: 1, to: task.date) ?? Date() + self.task.hasBeenDelayed = true + try? self.managedObjectContext.save() + } + config.showingDelay = false + } + } + Image(systemName: task.completed ? "checkmark.square" : "square") + .onTapGesture { + let generator = UIImpactFeedbackGenerator(style: .medium) + generator.prepare() + self.managedObjectContext.performAndWait { + self.task.completed.toggle() + if !self.task.daily { + self.task.date = Date.init() + } + try? self.managedObjectContext.save() + } + generator.impactOccurred() + } + Spacer() + if !config.editingText { + Text(task.name) + .strikethrough(task.completed) + .onTapGesture(count: 2) { + if !self.task.completed { + self.config.editingText = true + } + } + .onTapGesture { + self.config.showingNotes = true + } + } else { + TextField("edit task", text: $task.name) { + self.config.editingText = false + self.managedObjectContext.performAndWait { + try? self.managedObjectContext.save() + } + } + } + Spacer() + if !config.editingPriority { + HStack(alignment: .center, spacing: 2) { + ForEach(1 ..< Int(task.priority + 1), id: \.self) {_ in + Text("!") + } + } + .font(.system(size: 10, weight: .light)) + .onTapGesture(count: 2) { + if !self.task.completed { + self.config.editingPriority = true + } + } + } else { + Picker( + selection: priorityIntermediary, + label: Text("task priority"), + content: { + Text("!").tag(1) + Text("!!").tag(2) + Text("!!!").tag(3) + }) + .pickerStyle(SegmentedPickerStyle()) + } + if config.showingDelete { + Image(systemName: "trash.circle.fill") + .font(.system(size: 25)) + .foregroundColor(.red) + .onTapGesture { + self.managedObjectContext.performAndWait { + self.managedObjectContext.delete(self.task) + try? self.managedObjectContext.save() + } + } + } + } + .font(.system(size: 18, weight: .light)) + .foregroundColor(task.completed ? .secondary : .primary) + .multilineTextAlignment(.center) + .offset(x: config.offset) + .gesture( + DragGesture() + .onChanged({ value in + config.offset = direction == .leftToRight ? value.translation.width : -value.translation.width + }) + .onEnded({ value in + if task.daily && config.offset > 15 { + config.showingDelay.toggle() + } else if -config.offset > 15 { + config.showingDelete.toggle() + } + config.offset = 0 + }) + ) + .sheet(isPresented: $config.showingNotes, content: { + NoteSheet(task: self.task) + }) + } +} + +struct TaskViewConfig { + var editingText: Bool = false + var editingPriority: Bool = false + var showingNotes: Bool = false + var showingDelete: Bool = false + var showingDelay: Bool = false + var offset: CGFloat = 0 +} diff --git a/macOS/HomeHeaderView.swift b/macOS/HomeHeaderView.swift @@ -0,0 +1,26 @@ +// +// HomeHeaderView.swift +// txtodo +// +// Created by FIGBERT on 8/8/20. +// + +import SwiftUI + +struct HomeHeaderView: View { + var body: some View { + Text({ () -> String in + let formatter = DateFormatter() + formatter.dateStyle = .long + return formatter.string(from: Date()) + }()) + .font(.system(size: 20, weight: .bold)) + .padding(.horizontal) + } +} + +struct HomeHeaderView_Previews: PreviewProvider { + static var previews: some View { + HomeHeaderView() + } +} diff --git a/macOS/Info.plist b/macOS/Info.plist @@ -0,0 +1,28 @@ +<?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>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> + <key>CFBundleShortVersionString</key> + <string>3.0.0</string> + <key>CFBundleVersion</key> + <string>3.0.0</string> + <key>LSApplicationCategoryType</key> + <string>public.app-category.productivity</string> + <key>LSMinimumSystemVersion</key> + <string>$(MACOSX_DEPLOYMENT_TARGET)</string> +</dict> +</plist> diff --git a/macOS/SettingsView.swift b/macOS/SettingsView.swift @@ -0,0 +1,38 @@ +// +// SettingsView.swift +// txtodo (macOS) +// +// Created by FIGBERT on 8/6/20. +// + +import SwiftUI + +struct SettingsView: View { + var body: some View { + TabView { + VStack { + Text("txtodo by figbert - v\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String)") + Link(destination: URL(string: "https://txtodo.app/")!) { Text("view site") } + .padding() + Link(destination: URL(string: "https://jeffhuang.com/productivity_text_file/")!) { Text("view inspo") } + } + .tabItem { + Text("about") + Image(systemName: "book") + } + Form { NotificationSection() } + .padding() + .tabItem { + Text("notifications") + Image(systemName: "app.badge") + } + } + .frame(width: 300, height: 150) + } +} + +struct SettingsView_Previews: PreviewProvider { + static var previews: some View { + SettingsView() + } +} diff --git a/macOS/TaskView.swift b/macOS/TaskView.swift @@ -0,0 +1,156 @@ +// +// TaskView.swift +// txtodo +// +// Created by FIGBERT on 7/27/20. +// + +import SwiftUI + +struct TaskView: View { + @Environment(\.managedObjectContext) var managedObjectContext + @Environment(\.layoutDirection) var direction + @ObservedObject var task: Task + @State var priority: Int + @State private var config = TaskViewConfig() + + var body: some View { + let priorityIntermediary = Binding<Int>( + get: { self.priority }, + set: { value in + self.priority = value + self.managedObjectContext.performAndWait { + self.task.priority = Int16(value) + try? self.managedObjectContext.save() + } + self.config.editingPriority = false + } + ) + return VStack { + HStack { + if task.daily && !task.hasBeenDelayed && !task.completed && config.showingDelay { + Image(systemName: "calendar.circle.fill") + .font(.system(size: 25)) + .foregroundColor(.blue) + .onTapGesture { + self.managedObjectContext.performAndWait { + self.task.date = Calendar.current.date(byAdding: .day, value: 1, to: task.date) ?? Date() + self.task.hasBeenDelayed = true + try? self.managedObjectContext.save() + } + config.showingDelay = false + } + } + Image(systemName: task.completed ? "checkmark.square" : "square") + .onTapGesture { + self.managedObjectContext.performAndWait { + self.task.completed.toggle() + if !self.task.daily { + self.task.date = Date.init() + } + try? self.managedObjectContext.save() + } + self.config.showingNotes = false + } + Spacer() + if !config.editingText { + Text(task.name) + .strikethrough(task.completed) + .onTapGesture(count: 2) { + if !self.task.completed { + self.config.editingText = true + } + } + .onTapGesture { + self.config.showingNotes.toggle() + } + } else { + TextField("edit task", text: $task.name) { + self.config.editingText = false + self.managedObjectContext.performAndWait { + try? self.managedObjectContext.save() + } + } + } + Spacer() + if !config.editingPriority { + HStack(alignment: .center, spacing: 2) { + ForEach(1 ..< Int(task.priority + 1), id: \.self) {_ in + Text("!") + } + } + .font(.system(size: 10, weight: .light)) + .onTapGesture(count: 2) { + if !self.task.completed { + self.config.editingPriority = true + } + } + } else { + Picker( + selection: priorityIntermediary, + label: Text("task priority"), + content: { + Text("!").tag(1) + Text("!!").tag(2) + Text("!!!").tag(3) + }) + .pickerStyle(SegmentedPickerStyle()) + } + if config.showingDelete { + Image(systemName: "trash.circle.fill") + .font(.system(size: 25)) + .foregroundColor(.red) + .onTapGesture { + self.managedObjectContext.performAndWait { + self.managedObjectContext.delete(self.task) + try? self.managedObjectContext.save() + } + } + } + } + .padding(.bottom, 5) + .foregroundColor(task.completed ? .secondary : .primary) + .multilineTextAlignment(.center) + .offset(x: config.offset) + .gesture( + DragGesture() + .onChanged({ value in + config.offset = direction == .leftToRight ? value.translation.width : -value.translation.width + }) + .onEnded({ value in + if task.daily && config.offset > 15 { + config.showingDelay.toggle() + } else if -config.offset > 15 { + config.showingDelete.toggle() + } + config.offset = 0 + }) + ) + if config.showingNotes { + VStack(spacing: 10) { + ForEach(task.notes, id: \.self) { note in + NoteView(task: task, note: note) + .environment(\.managedObjectContext, self.managedObjectContext) + } + AddNoteView(task: task) + } + .padding(.leading) + .padding(.bottom, 5) + } + } + .padding(.vertical, config.showingNotes ? 12 : 0) + .padding(.horizontal, 14) + .background(config.showingNotes ? Color.gray.opacity(0.2) : .clear) + .cornerRadius(15) + .font(.system(size: 18, weight: .light)) + } +} + +struct TaskViewConfig { + var editingText: Bool = false + var editingPriority: Bool = false + var showingNotes: Bool = false + var showingDelete: Bool = false + var showingDelay: Bool = false + var offset: CGFloat = 0 +} diff --git a/macOS/macOS.entitlements b/macOS/macOS.entitlements @@ -0,0 +1,22 @@ +<?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>com.apple.developer.aps-environment</key> + <string>development</string> + <key>com.apple.developer.icloud-container-identifiers</key> + <array> + <string>iCloud.com.figbertind.txtodo</string> + </array> + <key>com.apple.developer.icloud-services</key> + <array> + <string>CloudKit</string> + </array> + <key>com.apple.security.app-sandbox</key> + <true/> + <key>com.apple.security.files.user-selected.read-only</key> + <true/> + <key>com.apple.security.network.client</key> + <true/> +</dict> +</plist> diff --git a/txtodo.entitlements b/txtodo.entitlements @@ -0,0 +1,16 @@ +<?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>aps-environment</key> + <string>development</string> + <key>com.apple.developer.icloud-container-identifiers</key> + <array> + <string>iCloud.com.figbertind.txtodo</string> + </array> + <key>com.apple.developer.icloud-services</key> + <array> + <string>CloudKit</string> + </array> +</dict> +</plist> diff --git a/txtodo.xcodeproj/project.pbxproj b/txtodo.xcodeproj/project.pbxproj @@ -0,0 +1,611 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 3A00ABE424CF7B3C0022FCCE /* txtodoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABD124CF7B3B0022FCCE /* txtodoApp.swift */; }; + 3A00ABE524CF7B3C0022FCCE /* txtodoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABD124CF7B3B0022FCCE /* txtodoApp.swift */; }; + 3A00ABE624CF7B3C0022FCCE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABD224CF7B3B0022FCCE /* ContentView.swift */; }; + 3A00ABE724CF7B3C0022FCCE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABD224CF7B3B0022FCCE /* ContentView.swift */; }; + 3A00ABE824CF7B3C0022FCCE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3A00ABD324CF7B3C0022FCCE /* Assets.xcassets */; }; + 3A00ABE924CF7B3C0022FCCE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3A00ABD324CF7B3C0022FCCE /* Assets.xcassets */; }; + 3A00ABF324CF820A0022FCCE /* TaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABF224CF820A0022FCCE /* TaskView.swift */; }; + 3A00ABF824CF82A50022FCCE /* txtodo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABF624CF82A50022FCCE /* txtodo.xcdatamodeld */; }; + 3A00ABF924CF82A50022FCCE /* txtodo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABF624CF82A50022FCCE /* txtodo.xcdatamodeld */; }; + 3A00ABFC24CF84110022FCCE /* Task+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABFA24CF84110022FCCE /* Task+CoreDataClass.swift */; }; + 3A00ABFD24CF84110022FCCE /* Task+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABFA24CF84110022FCCE /* Task+CoreDataClass.swift */; }; + 3A00ABFE24CF84110022FCCE /* Task+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABFB24CF84110022FCCE /* Task+CoreDataProperties.swift */; }; + 3A00ABFF24CF84110022FCCE /* Task+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A00ABFB24CF84110022FCCE /* Task+CoreDataProperties.swift */; }; + 3A31869624DBDB8200619154 /* NoteSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A31869524DBDB8200619154 /* NoteSheet.swift */; }; + 3A3B864F24E0AA4600740360 /* HomeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3B864E24E0AA4600740360 /* HomeHeaderView.swift */; }; + 3A57486C24DC9F9C00A4F8C0 /* AddNoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A57486B24DC9F9C00A4F8C0 /* AddNoteView.swift */; }; + 3A57486D24DC9F9C00A4F8C0 /* AddNoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A57486B24DC9F9C00A4F8C0 /* AddNoteView.swift */; }; + 3A5AC67A24D0D24000DD482F /* SectionLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5AC67924D0D24000DD482F /* SectionLabel.swift */; }; + 3A5AC67B24D0D24000DD482F /* SectionLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5AC67924D0D24000DD482F /* SectionLabel.swift */; }; + 3A74457124E33C6700788A32 /* TaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A74457024E33C6700788A32 /* TaskView.swift */; }; + 3A74457324E33D8500788A32 /* NoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A74457224E33D8500788A32 /* NoteView.swift */; }; + 3A74457424E33D8500788A32 /* NoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A74457224E33D8500788A32 /* NoteView.swift */; }; + 3A74457624E349B600788A32 /* DevicePaddingModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A74457524E349B600788A32 /* DevicePaddingModifiers.swift */; }; + 3A74457724E349B600788A32 /* DevicePaddingModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A74457524E349B600788A32 /* DevicePaddingModifiers.swift */; }; + 3AA0D6C824D8BCBA0052ADC8 /* AddTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA0D6C724D8BCBA0052ADC8 /* AddTask.swift */; }; + 3AA0D6C924D8BCBA0052ADC8 /* AddTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA0D6C724D8BCBA0052ADC8 /* AddTask.swift */; }; + 3ABD6A8724E0AC9A00B22F4B /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3ABD6A8624E0AC9A00B22F4B /* CloudKit.framework */; }; + 3ABD6A8924E0AD7900B22F4B /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3ABD6A8824E0AD7900B22F4B /* CloudKit.framework */; }; + 3ABD6A9024E0DB1B00B22F4B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ABD6A9324E0DB1B00B22F4B /* Localizable.strings */; }; + 3ABD6A9124E0DB1B00B22F4B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ABD6A9324E0DB1B00B22F4B /* Localizable.strings */; }; + 3ADE061524DFCF1E000C4289 /* HomeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ADE061424DFCEFE000C4289 /* HomeHeaderView.swift */; }; + 3AE1AE1E24DCE6D7005D88E2 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE1D24DCE6D7005D88E2 /* MenuView.swift */; }; + 3AE1AE2024DCECCC005D88E2 /* SettingsSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE1F24DCECCC005D88E2 /* SettingsSheet.swift */; }; + 3AE1AE2424DD19DC005D88E2 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE2324DD19DC005D88E2 /* SettingsView.swift */; }; + 3AE1AE2724DD2228005D88E2 /* NotificationSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE2624DD2228005D88E2 /* NotificationSection.swift */; }; + 3AE1AE2824DD2228005D88E2 /* NotificationSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE2624DD2228005D88E2 /* NotificationSection.swift */; }; + 3AE1AE2A24DD27BB005D88E2 /* FrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE2924DD27BB005D88E2 /* FrameModifier.swift */; }; + 3AE1AE2B24DD27BB005D88E2 /* FrameModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE2924DD27BB005D88E2 /* FrameModifier.swift */; }; + 3AE1AE2D24DD2A6E005D88E2 /* AboutSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE1AE2124DCECD5005D88E2 /* AboutSheet.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3A00ABD124CF7B3B0022FCCE /* txtodoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = txtodoApp.swift; sourceTree = "<group>"; }; + 3A00ABD224CF7B3B0022FCCE /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; + 3A00ABD324CF7B3C0022FCCE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; + 3A00ABD824CF7B3C0022FCCE /* txtodo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = txtodo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A00ABDB24CF7B3C0022FCCE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 3A00ABE024CF7B3C0022FCCE /* txtodo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = txtodo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A00ABE224CF7B3C0022FCCE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + 3A00ABE324CF7B3C0022FCCE /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = "<group>"; }; + 3A00ABF224CF820A0022FCCE /* TaskView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskView.swift; sourceTree = "<group>"; }; + 3A00ABF724CF82A50022FCCE /* txtodo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = txtodo.xcdatamodel; sourceTree = "<group>"; }; + 3A00ABFA24CF84110022FCCE /* Task+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Task+CoreDataClass.swift"; sourceTree = "<group>"; }; + 3A00ABFB24CF84110022FCCE /* Task+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Task+CoreDataProperties.swift"; sourceTree = "<group>"; }; + 3A31869524DBDB8200619154 /* NoteSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteSheet.swift; sourceTree = "<group>"; }; + 3A3B864E24E0AA4600740360 /* HomeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeHeaderView.swift; sourceTree = "<group>"; }; + 3A57486B24DC9F9C00A4F8C0 /* AddNoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddNoteView.swift; sourceTree = "<group>"; }; + 3A5AC67924D0D24000DD482F /* SectionLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionLabel.swift; sourceTree = "<group>"; }; + 3A74457024E33C6700788A32 /* TaskView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskView.swift; sourceTree = "<group>"; }; + 3A74457224E33D8500788A32 /* NoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteView.swift; sourceTree = "<group>"; }; + 3A74457524E349B600788A32 /* DevicePaddingModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevicePaddingModifiers.swift; sourceTree = "<group>"; }; + 3AA0D6C724D8BCBA0052ADC8 /* AddTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTask.swift; sourceTree = "<group>"; }; + 3ABD6A8424E0AC9600B22F4B /* txtodo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = txtodo.entitlements; sourceTree = "<group>"; }; + 3ABD6A8624E0AC9A00B22F4B /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/CloudKit.framework; sourceTree = DEVELOPER_DIR; }; + 3ABD6A8824E0AD7900B22F4B /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; }; + 3ABD6A9224E0DB1B00B22F4B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; + 3ABD6A9424E0DB5800B22F4B /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = "<group>"; }; + 3ADE061424DFCEFE000C4289 /* HomeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeHeaderView.swift; sourceTree = "<group>"; }; + 3AE1AE1D24DCE6D7005D88E2 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = "<group>"; }; + 3AE1AE1F24DCECCC005D88E2 /* SettingsSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSheet.swift; sourceTree = "<group>"; }; + 3AE1AE2124DCECD5005D88E2 /* AboutSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutSheet.swift; sourceTree = "<group>"; }; + 3AE1AE2324DD19DC005D88E2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; + 3AE1AE2624DD2228005D88E2 /* NotificationSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSection.swift; sourceTree = "<group>"; }; + 3AE1AE2924DD27BB005D88E2 /* FrameModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameModifier.swift; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3A00ABD524CF7B3C0022FCCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3ABD6A8724E0AC9A00B22F4B /* CloudKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A00ABDD24CF7B3C0022FCCE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3ABD6A8924E0AD7900B22F4B /* CloudKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3A00ABCB24CF7B3A0022FCCE = { + isa = PBXGroup; + children = ( + 3A00ABD024CF7B3B0022FCCE /* Shared */, + 3A00ABDA24CF7B3C0022FCCE /* iOS */, + 3A00ABE124CF7B3C0022FCCE /* macOS */, + 3A00ABD924CF7B3C0022FCCE /* Products */, + 3ABD6A8524E0AC9A00B22F4B /* Frameworks */, + 3ABD6A8424E0AC9600B22F4B /* txtodo.entitlements */, + ); + sourceTree = "<group>"; + }; + 3A00ABD024CF7B3B0022FCCE /* Shared */ = { + isa = PBXGroup; + children = ( + 3A00ABD124CF7B3B0022FCCE /* txtodoApp.swift */, + 3A00ABD224CF7B3B0022FCCE /* ContentView.swift */, + 3A74457224E33D8500788A32 /* NoteView.swift */, + 3AA0D6C724D8BCBA0052ADC8 /* AddTask.swift */, + 3A57486B24DC9F9C00A4F8C0 /* AddNoteView.swift */, + 3A5AC67924D0D24000DD482F /* SectionLabel.swift */, + 3AE1AE2924DD27BB005D88E2 /* FrameModifier.swift */, + 3A74457524E349B600788A32 /* DevicePaddingModifiers.swift */, + 3ABD6A9324E0DB1B00B22F4B /* Localizable.strings */, + 3AE1AE2524DD21FF005D88E2 /* Settings Views */, + 3A00ABF524CF828F0022FCCE /* Data Models */, + 3A00ABD324CF7B3C0022FCCE /* Assets.xcassets */, + ); + path = Shared; + sourceTree = "<group>"; + }; + 3A00ABD924CF7B3C0022FCCE /* Products */ = { + isa = PBXGroup; + children = ( + 3A00ABD824CF7B3C0022FCCE /* txtodo.app */, + 3A00ABE024CF7B3C0022FCCE /* txtodo.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 3A00ABDA24CF7B3C0022FCCE /* iOS */ = { + isa = PBXGroup; + children = ( + 3A3B864E24E0AA4600740360 /* HomeHeaderView.swift */, + 3A00ABF224CF820A0022FCCE /* TaskView.swift */, + 3A31869524DBDB8200619154 /* NoteSheet.swift */, + 3AE1AE1D24DCE6D7005D88E2 /* MenuView.swift */, + 3AE1AE1F24DCECCC005D88E2 /* SettingsSheet.swift */, + 3AE1AE2124DCECD5005D88E2 /* AboutSheet.swift */, + 3A00ABDB24CF7B3C0022FCCE /* Info.plist */, + ); + path = iOS; + sourceTree = "<group>"; + }; + 3A00ABE124CF7B3C0022FCCE /* macOS */ = { + isa = PBXGroup; + children = ( + 3ADE061424DFCEFE000C4289 /* HomeHeaderView.swift */, + 3A74457024E33C6700788A32 /* TaskView.swift */, + 3AE1AE2324DD19DC005D88E2 /* SettingsView.swift */, + 3A00ABE224CF7B3C0022FCCE /* Info.plist */, + 3A00ABE324CF7B3C0022FCCE /* macOS.entitlements */, + ); + path = macOS; + sourceTree = "<group>"; + }; + 3A00ABF524CF828F0022FCCE /* Data Models */ = { + isa = PBXGroup; + children = ( + 3A00ABF624CF82A50022FCCE /* txtodo.xcdatamodeld */, + 3A00ABFA24CF84110022FCCE /* Task+CoreDataClass.swift */, + 3A00ABFB24CF84110022FCCE /* Task+CoreDataProperties.swift */, + ); + path = "Data Models"; + sourceTree = "<group>"; + }; + 3ABD6A8524E0AC9A00B22F4B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3ABD6A8824E0AD7900B22F4B /* CloudKit.framework */, + 3ABD6A8624E0AC9A00B22F4B /* CloudKit.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 3AE1AE2524DD21FF005D88E2 /* Settings Views */ = { + isa = PBXGroup; + children = ( + 3AE1AE2624DD2228005D88E2 /* NotificationSection.swift */, + ); + path = "Settings Views"; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3A00ABD724CF7B3C0022FCCE /* txtodo (iOS) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3A00ABEC24CF7B3C0022FCCE /* Build configuration list for PBXNativeTarget "txtodo (iOS)" */; + buildPhases = ( + 3A00ABD424CF7B3C0022FCCE /* Sources */, + 3A00ABD524CF7B3C0022FCCE /* Frameworks */, + 3A00ABD624CF7B3C0022FCCE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "txtodo (iOS)"; + productName = "txtodo (iOS)"; + productReference = 3A00ABD824CF7B3C0022FCCE /* txtodo.app */; + productType = "com.apple.product-type.application"; + }; + 3A00ABDF24CF7B3C0022FCCE /* txtodo (macOS) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3A00ABEF24CF7B3C0022FCCE /* Build configuration list for PBXNativeTarget "txtodo (macOS)" */; + buildPhases = ( + 3A00ABDC24CF7B3C0022FCCE /* Sources */, + 3A00ABDD24CF7B3C0022FCCE /* Frameworks */, + 3A00ABDE24CF7B3C0022FCCE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "txtodo (macOS)"; + productName = "txtodo (macOS)"; + productReference = 3A00ABE024CF7B3C0022FCCE /* txtodo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3A00ABCC24CF7B3A0022FCCE /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1200; + LastUpgradeCheck = 1200; + TargetAttributes = { + 3A00ABD724CF7B3C0022FCCE = { + CreatedOnToolsVersion = 12.0; + }; + 3A00ABDF24CF7B3C0022FCCE = { + CreatedOnToolsVersion = 12.0; + }; + }; + }; + buildConfigurationList = 3A00ABCF24CF7B3A0022FCCE /* Build configuration list for PBXProject "txtodo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + he, + ); + mainGroup = 3A00ABCB24CF7B3A0022FCCE; + productRefGroup = 3A00ABD924CF7B3C0022FCCE /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3A00ABD724CF7B3C0022FCCE /* txtodo (iOS) */, + 3A00ABDF24CF7B3C0022FCCE /* txtodo (macOS) */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3A00ABD624CF7B3C0022FCCE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A00ABE824CF7B3C0022FCCE /* Assets.xcassets in Resources */, + 3ABD6A9024E0DB1B00B22F4B /* Localizable.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A00ABDE24CF7B3C0022FCCE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A00ABE924CF7B3C0022FCCE /* Assets.xcassets in Resources */, + 3ABD6A9124E0DB1B00B22F4B /* Localizable.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3A00ABD424CF7B3C0022FCCE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3AE1AE2024DCECCC005D88E2 /* SettingsSheet.swift in Sources */, + 3AE1AE2D24DD2A6E005D88E2 /* AboutSheet.swift in Sources */, + 3A00ABF324CF820A0022FCCE /* TaskView.swift in Sources */, + 3A31869624DBDB8200619154 /* NoteSheet.swift in Sources */, + 3A00ABFC24CF84110022FCCE /* Task+CoreDataClass.swift in Sources */, + 3A00ABF824CF82A50022FCCE /* txtodo.xcdatamodeld in Sources */, + 3AA0D6C824D8BCBA0052ADC8 /* AddTask.swift in Sources */, + 3A00ABE624CF7B3C0022FCCE /* ContentView.swift in Sources */, + 3AE1AE2724DD2228005D88E2 /* NotificationSection.swift in Sources */, + 3AE1AE2A24DD27BB005D88E2 /* FrameModifier.swift in Sources */, + 3A74457624E349B600788A32 /* DevicePaddingModifiers.swift in Sources */, + 3A5AC67A24D0D24000DD482F /* SectionLabel.swift in Sources */, + 3AE1AE1E24DCE6D7005D88E2 /* MenuView.swift in Sources */, + 3A74457324E33D8500788A32 /* NoteView.swift in Sources */, + 3A3B864F24E0AA4600740360 /* HomeHeaderView.swift in Sources */, + 3A00ABFE24CF84110022FCCE /* Task+CoreDataProperties.swift in Sources */, + 3A00ABE424CF7B3C0022FCCE /* txtodoApp.swift in Sources */, + 3A57486C24DC9F9C00A4F8C0 /* AddNoteView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3A00ABDC24CF7B3C0022FCCE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A74457124E33C6700788A32 /* TaskView.swift in Sources */, + 3A00ABFD24CF84110022FCCE /* Task+CoreDataClass.swift in Sources */, + 3A00ABF924CF82A50022FCCE /* txtodo.xcdatamodeld in Sources */, + 3AA0D6C924D8BCBA0052ADC8 /* AddTask.swift in Sources */, + 3A00ABE724CF7B3C0022FCCE /* ContentView.swift in Sources */, + 3A5AC67B24D0D24000DD482F /* SectionLabel.swift in Sources */, + 3A00ABFF24CF84110022FCCE /* Task+CoreDataProperties.swift in Sources */, + 3A74457724E349B600788A32 /* DevicePaddingModifiers.swift in Sources */, + 3AE1AE2824DD2228005D88E2 /* NotificationSection.swift in Sources */, + 3A00ABE524CF7B3C0022FCCE /* txtodoApp.swift in Sources */, + 3A57486D24DC9F9C00A4F8C0 /* AddNoteView.swift in Sources */, + 3AE1AE2424DD19DC005D88E2 /* SettingsView.swift in Sources */, + 3ADE061524DFCF1E000C4289 /* HomeHeaderView.swift in Sources */, + 3A74457424E33D8500788A32 /* NoteView.swift in Sources */, + 3AE1AE2B24DD27BB005D88E2 /* FrameModifier.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3ABD6A9324E0DB1B00B22F4B /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 3ABD6A9224E0DB1B00B22F4B /* en */, + 3ABD6A9424E0DB5800B22F4B /* he */, + ); + name = Localizable.strings; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3A00ABEA24CF7B3C0022FCCE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 3A00ABEB24CF7B3C0022FCCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 3A00ABED24CF7B3C0022FCCE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = txtodo.entitlements; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 9WHCFZ6J4N; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = iOS/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.figbertind.txtodo; + PRODUCT_NAME = txtodo; + SDKROOT = iphoneos; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3A00ABEE24CF7B3C0022FCCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = txtodo.entitlements; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 9WHCFZ6J4N; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = iOS/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.figbertind.txtodo; + PRODUCT_NAME = txtodo; + SDKROOT = iphoneos; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3A00ABF024CF7B3C0022FCCE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 9WHCFZ6J4N; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = macOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_BUNDLE_IDENTIFIER = com.figbertind.txtodo; + PRODUCT_NAME = txtodo; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 3A00ABF124CF7B3C0022FCCE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 9WHCFZ6J4N; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = macOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_BUNDLE_IDENTIFIER = com.figbertind.txtodo; + PRODUCT_NAME = txtodo; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3A00ABCF24CF7B3A0022FCCE /* Build configuration list for PBXProject "txtodo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A00ABEA24CF7B3C0022FCCE /* Debug */, + 3A00ABEB24CF7B3C0022FCCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3A00ABEC24CF7B3C0022FCCE /* Build configuration list for PBXNativeTarget "txtodo (iOS)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A00ABED24CF7B3C0022FCCE /* Debug */, + 3A00ABEE24CF7B3C0022FCCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3A00ABEF24CF7B3C0022FCCE /* Build configuration list for PBXNativeTarget "txtodo (macOS)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3A00ABF024CF7B3C0022FCCE /* Debug */, + 3A00ABF124CF7B3C0022FCCE /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + 3A00ABF624CF82A50022FCCE /* txtodo.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + 3A00ABF724CF82A50022FCCE /* txtodo.xcdatamodel */, + ); + currentVersion = 3A00ABF724CF82A50022FCCE /* txtodo.xcdatamodel */; + path = txtodo.xcdatamodeld; + sourceTree = "<group>"; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = 3A00ABCC24CF7B3A0022FCCE /* Project object */; +} diff --git a/txtodo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/txtodo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/txtodo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/txtodo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -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>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist>