Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Examples/AppKitDemo/App.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import CasePaths
import Observation

@Observable
final class AppModel {

var destination: Destination?

init(destination: Destination? = nil) {
self.destination = destination
}

func reminderSelectedInOutline(_ reminder: Reminder) {
self.destination = .reminder(ReminderDetailModel(reminder: reminder))
}

func remindersListSelectedInOutline(_ remindersList: RemindersList) {
self.destination = .remindersList(RemindersListDetailModel(remindersList: remindersList))
}

@CasePathable
enum Destination {
case reminder(ReminderDetailModel)
case remindersList(RemindersListDetailModel)
}
}
89 changes: 89 additions & 0 deletions Examples/AppKitDemo/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import AppKit
import Dependencies
import SQLiteData

@MainActor
public final class AppDelegate: NSObject, NSApplicationDelegate {
private var windowControllers: [DemoWindowController] = []

public func applicationWillFinishLaunching(_ notification: Notification) {
let appMenu = NSMenuItem()
appMenu.submenu = NSMenu()
appMenu.submenu?.items = [
NSMenuItem(
title: "New Window",
action: #selector(AppDelegate.newDemoWindow),
keyEquivalent: "n"
),
NSMenuItem(
title: "Close Window",
action: #selector(NSWindow.performClose(_:)),
keyEquivalent: "w"
),
NSMenuItem(
title: "Quit",
action: #selector(NSApplication.terminate(_:)),
keyEquivalent: "q"
),
]
let mainMenu = NSMenu()
mainMenu.items = [appMenu]
NSApplication.shared.mainMenu = mainMenu
}
public func applicationDidFinishLaunching(_ notification: Notification) {
try! prepareDependencies {
try $0.bootstrapDatabase()
}
@Dependency(\.defaultDatabase) var database
try! database.write { db in
try db.seedSampleData()
}
newDemoWindow()
}
}

extension AppDelegate {
@objc func newDemoWindow() {
let windowController = DemoWindowController()
windowController.showWindow(nil)
windowControllers.append(windowController)
}
func removeWindowController(_ controller: DemoWindowController) {
windowControllers.removeAll { $0 === controller }
}
}

final class DemoWindowController: NSWindowController {
init() {
let window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
styleMask: [
.fullSizeContentView,
.closable,
.miniaturizable,
.resizable,
.titled,
],
backing: .buffered,
defer: false
)

window.titleVisibility = .visible
window.toolbarStyle = .unified
window.center()

super.init(window: window)

window.contentViewController = RootViewController(
model: AppModel()
)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func windowWillClose(_ notification: Notification) {
if let appDelegate = NSApp.delegate as? AppDelegate {
appDelegate.removeWindowController(self)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"images" : [
{
"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
}
}
6 changes: 6 additions & 0 deletions Examples/AppKitDemo/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
97 changes: 97 additions & 0 deletions Examples/AppKitDemo/DetailViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import AppKit
import CasePaths
import SQLiteData
import SwiftUI

final class DetailViewController: NSViewController {
let model: AppModel
init(model: AppModel) {
self.model = model
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
let hostingView = FullSizeHostingView(
rootView: DetailView(model: model)
.frame(
minWidth: 600,
maxWidth: .infinity,
minHeight: 500,
maxHeight: .infinity
)
)
self.view = hostingView
}
class FullSizeHostingView<Content: View>: NSHostingView<Content> {
override var intrinsicContentSize: NSSize {
return NSSize(width: NSView.noIntrinsicMetric, height: NSView.noIntrinsicMetric)
}
}
}

private struct DetailView: View {
let model: AppModel
var body: some View {
switch model.destination {
case .remindersList(let model):
RemindersListDetailView(model: model)
case .reminder(let model):
ReminderDetailView(model: model)
case .none:
ContentUnavailableView(
"Choose a reminder or list",
systemImage: "list.bullet"
)
}
}
}

#Preview("Empty") {
let remindersList = try! prepareDependencies {
try $0.bootstrapDatabase()
return try $0.defaultDatabase.read { db in
try RemindersList.all.fetchOne(db)!
}
}
DetailViewController(
model: AppModel()
)
}

#Preview("RemindersList") {
let remindersList = try! prepareDependencies {
try $0.bootstrapDatabase()
return try $0.defaultDatabase.read { db in
try RemindersList.all.fetchOne(db)!
}
}
DetailViewController(
model: AppModel(
destination: .remindersList(
RemindersListDetailModel(
remindersList: remindersList
)
)
)
)
}

#Preview("Reminder") {
let reminder = try! prepareDependencies {
try $0.bootstrapDatabase()
return try $0.defaultDatabase.read { db in
try Reminder.all.fetchOne(db)!
}
}
DetailViewController(
model: AppModel(
destination: .reminder(
ReminderDetailModel(
reminder: reminder
)
)
)
)
}
35 changes: 35 additions & 0 deletions Examples/AppKitDemo/ReminderDetail.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import SQLiteData
import SwiftUI

@MainActor
@Observable
final class ReminderDetailModel {
@ObservationIgnored @FetchOne var reminder: Reminder
init(reminder: Reminder) {
_reminder = FetchOne(
wrappedValue: reminder,
Reminder.find(reminder.id)
)
}
}

struct ReminderDetailView: View {
let model: ReminderDetailModel
var body: some View {
Text(model.reminder.title)
}
}

#Preview("Reminder") {
let reminder = try! prepareDependencies {
try $0.bootstrapDatabase()
return try $0.defaultDatabase.read { db in
try Reminder.all.fetchOne(db)!
}
}
ReminderDetailView(
model: ReminderDetailModel(
reminder: reminder
)
)
}
52 changes: 52 additions & 0 deletions Examples/AppKitDemo/RemindersListDetail.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import SQLiteData
import SwiftUI

@MainActor
@Observable
final class RemindersListDetailModel {
@ObservationIgnored @FetchOne var remindersList: RemindersList
@ObservationIgnored @FetchAll var reminders: [Reminder]
var editableRemindersList: RemindersList.Draft?
init(remindersList: RemindersList) {
_remindersList = FetchOne(
wrappedValue: remindersList,
RemindersList.find(remindersList.id)
)
_reminders = FetchAll(
Reminder.all
.where { $0.remindersListID.eq(remindersList.id) }
.order {
($0.isCompleted, $0.title)
}
)
}
}

struct RemindersListDetailView: View {
let model: RemindersListDetailModel
var body: some View {
List {
ForEach(model.reminders) { reminder in
Text(reminder.title)
}
}
.safeAreaInset(edge: .top) {
Text(model.remindersList.title)
.font(.headline)
}
}
}

#Preview {
let remindersList = try! prepareDependencies {
try $0.bootstrapDatabase()
return try $0.defaultDatabase.read { db in
try RemindersList.all.fetchOne(db)!
}
}
RemindersListDetailView(
model: RemindersListDetailModel(
remindersList: remindersList
)
)
}
Loading