Devlog: July 17, 2023

I submitted ScreenCred for review yesterday. After listening to the latest ATP today, I’m expecting some rejections around my use of movie and show posters in the screenshots, and potentially in the app. If it get’s rejected, I’m not sure how much effort I’m going to put into resolving issues. While I’ve spent a lot of time on the app (3–5 hours a week for the last 7 months or so…) I know it’s a niche app that would not likely be wildly successful. Probably not even mildly successful. But I would still like it to be on the App Store, for myself.

I have another app I want to work on with my wife for our kids. That one might have a better chance. So part of submitting ScreenCred was to help clear the decks before starting on that in earnest.

So we’ll see what happens! Perfect world, it sails through app review and makes enough to pay for it’s own server costs and more!

Projects ScreenCred devlog

Devlog: July 13, 2023

Needed some easy wins today. So I worked on adding some simple pages to screencred.app for support, press kit, and terms. Press kit still needs screenshots and stuff.

I also found some issues with the App Clip—wrong colors and a placeholder view. I will get those fixed tomorrow.

Projects ScreenCred devlog

Devlog: July 11, 2023

I knew I had seen. Feature in Swift strings that could automatically pluralize words depending on a value. Took me a while to find the actual thing I wanted. Turns out it’s called morphology. Jordan Morgan has a great post about it.

It works nicely when using Text in SwiftUI:

Text("Last compared \(timestamp.formatted()) and seen ^[\(historyItems.count) time](inflect: true)")

It’s not the nicest syntax, but better than doing it all myself.

Projects ScreenCred devlog

Devlog: June 24, 2023

As part of my efforts to improve accessibility in ScreenCred, I’ve been working at improving layouts for large Dynamic Type sizes. To help with this, I’m trying to use ViewThatFits. It works as I’d expect in most places. However, I had a lot of issues when trying to use it within a ScrollView for repeating items. I’m sure that a lot of my issues are from not really knowing how ViewThatFits chooses which view to use. What is fits”? I’m not 100% sure.

In ScreenCreds, I have a couple places with lists and I want every item in that list to either be a horizontal layout or a vertical layout, but not a mix of both.

On an individual view, ViewThatFits works real well:

ViewThatFits {
    HStack {
        Image(item.image)
        Text(item.label)
    }
    VStack {
        Image(item.image)
        Text(item.label)
    }
}

If the text gets too long, it will switch to use the VStack View. But, if I put that in a ForEach, which view that fits is dependent on the content, so some items may use HStack and others will VStack. Not what I want.

ScrollView {
    ForEach(item) { item in
        ViewThatFits {
            HStack {
                Image(item.image)
                Text(item.label)
            }
            VStack {
                Image(item.image)
                Text(item.label)
            }
        }
    }
}

So I thought, easy, just put two ForEaches:

ScrollView {
    ViewThatFits {
        ForEach(item) { item in
            HStack {
                Image(item.image)
                Text(item.label)
            }
        }
        ForEach(item) { item in
            VStack {
                Image(item.image)
                Text(item.label)
            }
        }
    }
}

Unfortunately, this did not work. No matter what I tried, it always picked the second View. The only way I found to fix this is to switch between ScrollViews:

ViewThatFits
    ScrollView {
        ForEach(item) { item in
            HStack {
                Image(item.image)
                Text(item.label)
            }
        }
    }
    ScrollView {
        ForEach(item) { item in
            VStack {
                Image(item.image)
                Text(item.label)
            }
        }
    }
}

The way my views are constructed, it wasn’t as simple as this. It would’ve been tricky to refactor things to work like this. So I came up with a solution to use an Environment value.

enum Layout {
    case horizontal, vertical
}

private struct LayoutKey: EnvironmentKey {
    static let defaultValue = Layout.horizontal
}

extension EnvironmentValues {
    var layout: Layout {
    get { self[LayoutKey.self] }
    set { self[LayoutKey.self] = newValue }
  }
}

ViewThatFits {
    Main()
        .environment(\.layout, .horizontal)
    Main()
        .environment(\.layout, .vertical)
}

In this case, the ScrollView is a few views deep in Main. Each repeated item is a few views deeper. But, at the point I need to decide which layout to use, I can grab my layout Environment value.

So far, this seems to work the way I want! I’m not totally sure if this is performant or not.

Screen recording of ScreenCred showing the layout changing when using large Dynamic TypeScreen recording of ScreenCred showing the layout changing when using large Dynamic Type

I was really glad I was able to get ViewThatFits to work. The only other alternative was changing layouts at some arbitrary sizeCategory. That would be gross because it would depend on screen size and all that.

SO hopefully this will continue to work well. I should probably rewatch the WWDC video about ViewThatFits.

P.S. In places I couldn’t use the Xcode Previews, I’ve been using Sim Genie to easily change Dynamic Type in the simulator. Fantastic app.

Projects ScreenCred devlog

Devlog: June 21, 2023

Not sure what happened, but I was no longer able to access https://screencred.app. I’m hosting it on fly.io, and using Cloudflare in front of it. Seemed like the fly.io certificate expired.

The trick seemed to be that I needed to make sure my _acme-challenge CNAME record is unproxied, but keep the A and AAAA records proxied in Cloudflare. I now see that the fly.io certificate has been renewed. So hopefully that’s all it is.

devlog

Devlog: June 15, 2023

Quick report. Been going through ScreenCred with Voice Over and on an iPhone 13 mini simulator with Accessibility Extra Extra Extra Large Dynamic Type enabled. So far I have found about 30 things that need to be fixed and improved. Most are small, simple things. Others are going to require new designs at larger text sizes. I’ll get those fixed and then go through it all again.

Projects ScreenCred devlog

Picture of Sam Warnick

As my daughter says, I'm just a tired dad, with a tired name, Sam Warnick. I'm a software developer in Beaufort, SC.

Some things I do