@sean
🔥 1 day streak
412 words

Making a swift macOS password manager for people who hate the cloud

<- For Day 5 go here

I'm going to start laying out these posts a little better, more like a timeline, I think that could be cool and more instructive as to how much I actually spent working on this thing so I can calculate how little $/hr I make when I try to sell it for $29/lifetime and maybe put it on Setapp. I'm hoping it's at least minimum wage, but based on my past side projects I doubt it.

11:06 AM MT

Decide what I want to work on today. I'm kind of falling behind so I really need to figure out the fastest way to get data from the AddLoginViewController into SQLite and Keychain

11:47 AM MT

This is what a tiny bit of success looks like, it ain't pretty, but ITS WORKING. My problems were two fold, one the ContainerView button wasn't firing, turns out I needed to call addChild on the AddNewLoginViewController to get it working like so

    @IBAction func addNewLogin(_ sender: NSMenuItem) {
        let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
        let vc = storyboard.instantiateController(withIdentifier: "AddLoginViewController") as! NSViewController

        for sView in containerView.subviews {
            sView.removeFromSuperview()
        }

        addChild(vc)
        vc.view.frame = containerView.bounds
        containerView.addSubview(vc.view)
    }

Then from there the button was firing so SQLite.swift could take over

    @IBAction func addButtonClicked(_ sender: NSButton) {
        print("clicked")
        let login = Login()
        let db = Database.open()
        try! db.run(login.table.insert(login.email <- emailTextField.stringValue, login.username <- usernameTextField.stringValue, login.key <- UUID.init().uuidString))

        for row in try! db.prepare(login.table) {
            print("id: \(row[login.id]), key: \(row[login.key]), email: \(row[login.email]), name: \(row[login.username])")
        }
    }

Oh I also added a few structs there for opening the db connection and wrapping the struct table definition:

import SQLite

public struct Database {
    static func open() -> Connection {
        let path = NSSearchPathForDirectoriesInDomains(
            .applicationSupportDirectory, .userDomainMask, true
            ).first! + "/" + Bundle.main.bundleIdentifier!

        do {
            try FileManager.default.createDirectory(
                atPath: path, withIntermediateDirectories: true, attributes: nil
            )
        } catch {
            print("Unexpected error: \(error).")
        }

        var conn : Connection?
        do {
            conn = try Connection("\(path)/app.db")
        } catch {
            print("Unexpected error: \(error).")
        }

        return conn!
    }
}

public struct Login {
    let table = Table("login")
    let id = Expression<Int64>("id")
    let url = Expression<String?>("url")
    let username = Expression<String?>("username")
    let email = Expression<String?>("email")
    let key = Expression<String>("key")
}

So now it's just polish work, kind of like this