Skip to content

Commit

Permalink
Macro fixes (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
noahsmartin authored Jan 17, 2025
1 parent d631600 commit 55198bb
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 67 deletions.
23 changes: 9 additions & 14 deletions Sources/PreviewGallery/ModulePreviews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,30 @@ import SwiftUI
struct ModulePreviews: View {
let module: String
let data: PreviewData

var body: some View {
let componentProviders = data.previews(in: module).filter { provider in
return provider.previews.contains { preview in
return !preview.requiresFullScreen
}
}
let featureProviders = data.previews(in: module).filter { provider in
return provider.previews.contains { preview in
return preview.requiresFullScreen
}
let allPreviewGroups = data.previews(in: module)
let componentProviders = allPreviewGroups.filter { provider in
provider.previewTypes(requiringFullscreen: false).count > 0
}
let fullScreenCount = allPreviewGroups.flatMap { $0.previews.flatMap { $0.previews(requiringFullscreen: true)} }.count
return NavigationLink(module) {
ScrollView {
LazyVStack(alignment: .leading, spacing: 12) {
if !featureProviders.isEmpty {
if fullScreenCount > 0 {
NavigationLink(destination: ModuleScreens(module: module, data: data)) {
TitleSubtitleRow(
title: "Screens",
subtitle: "\(featureProviders.count) Preview\(featureProviders.count != 1 ? "s" : "")")
subtitle: "\(fullScreenCount) Preview\(fullScreenCount != 1 ? "s" : "")")
.padding(16)
#if !os(watchOS)
.background(Color(PlatformColor.gallerySecondaryBackground))
#endif
}
}
ForEach(componentProviders) { preview in
NavigationLink(destination: PreviewsDetail(previewType: preview)) {
PreviewCellView(preview: preview)
NavigationLink(destination: PreviewsDetail(previewGrouping: preview)) {
PreviewCellView(previewGrouping: preview)
#if !os(watchOS)
.background(Color(PlatformColor.gallerySecondaryBackground))
#endif
Expand Down
8 changes: 3 additions & 5 deletions Sources/PreviewGallery/ModuleScreens.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import SwiftUI
import SnapshotPreviewsCore

struct ModuleSelectionView: View {
let provider: SnapshotPreviewsCore.PreviewType
let provider: PreviewGrouping
var body: some View {
let featurePreviews = provider.previews.filter { $0.requiresFullScreen }
let featurePreviews = provider.previews.flatMap(\.previews).filter { $0.requiresFullScreen }
NavigationLink {
if featurePreviews.count == 1 {
AnyView(featurePreviews[0].view())
Expand Down Expand Up @@ -48,9 +48,7 @@ struct ModuleScreens: View {

var body: some View {
let featureProviders = data.previews(in: module).filter { provider in
return provider.previews.contains { preview in
return preview.requiresFullScreen
}
!provider.previewTypes(requiringFullscreen: true).isEmpty
}
return List {
ForEach(featureProviders) { provider in
Expand Down
6 changes: 6 additions & 0 deletions Sources/PreviewGallery/Preview+FullScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ extension Preview {
}

}

extension PreviewType {
func previews(requiringFullscreen: Bool) -> [Preview] {
previews.filter { $0.requiresFullScreen == requiringFullscreen }
}
}
23 changes: 21 additions & 2 deletions Sources/PreviewGallery/PreviewData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
import Foundation
import SnapshotPreviewsCore

struct PreviewGrouping: Identifiable {
let id: String

var displayName: String {
previews[0].displayName
}

func previewTypes(requiringFullscreen: Bool) -> [PreviewType] {
return previews.filter { !$0.previews(requiringFullscreen: requiringFullscreen).isEmpty }
}

let previews: [PreviewType]
}


/// A structure that manages a collection of preview types.
///
Expand All @@ -30,8 +44,13 @@ public struct PreviewData {
///
/// - Parameter module: The name of the module to filter previews for.
/// - Returns: An array of `PreviewType` instances belonging to the specified module, sorted by type name.
func previews(in module: String) -> [PreviewType] {
previews.filter { $0.module == module }.sorted { $0.typeName < $1.typeName }
func previews(in module: String) -> [PreviewGrouping] {
let modulePreviews = previews.filter { $0.module == module }
return Dictionary(grouping: modulePreviews) { p in
p.fileID ?? p.typeName
}.values.map { previews in
PreviewGrouping(id: previews[0].fileID ?? previews[0].typeName, previews: previews)
}.sorted { $0.displayName < $1.displayName }
}

/// A set of all unique module names represented in the previews.
Expand Down
12 changes: 8 additions & 4 deletions Sources/PreviewGallery/PreviewGallery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ import SwiftUI
import SnapshotPreviewsCore

struct PreviewCellView: View {
let preview: PreviewType
let previewGrouping: PreviewGrouping

var previews: [SnapshotPreviewsCore.Preview] {
previewGrouping.previews.flatMap { $0.previews(requiringFullscreen: false)}
}

var body: some View {
VStack(alignment: .center) {
TitleSubtitleRow(
title: preview.displayName,
subtitle: "\(preview.previews.count) Preview\(preview.previews.count != 1 ? "s" : "")"
title: previewGrouping.displayName,
subtitle: "\(previews.count) Preview\(previews.count != 1 ? "s" : "")"
)
.padding(EdgeInsets(top: 12, leading: 16, bottom: 6, trailing: 16))

PreviewCell(preview: preview.previews[0])
PreviewCell(preview: previews[0])
}
.padding(.bottom, 8)
}
Expand Down
12 changes: 8 additions & 4 deletions Sources/PreviewGallery/PreviewsDetail.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import SnapshotPreviewsCore

struct PreviewsDetail: View {

let previewType: PreviewType

let previewGrouping: PreviewGrouping

var previews: [SnapshotPreviewsCore.Preview] {
previewGrouping.previews.flatMap { $0.previews(requiringFullscreen: false) }
}

var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 12) {
ForEach(previewType.previews) { preview in
ForEach(previews) { preview in
VStack(alignment: .center) {
Text(preview.displayName ?? "Preview")
.font(.headline)
Expand All @@ -36,7 +40,7 @@ struct PreviewsDetail: View {
#if !os(watchOS)
.background(Color(PlatformColor.galleryBackground))
#endif
.navigationTitle(previewType.displayName)
.navigationTitle(previewGrouping.displayName)
}

}
42 changes: 4 additions & 38 deletions Sources/SnapshotPreviewsCore/SnapshotPreviewsCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,13 @@ public struct PreviewType: Hashable, Identifiable {

public var displayName: String {
if let fileID = fileID {
return String(fileID.split(separator: "/").last!.split(separator: ".").first!)
return String(fileID.split(separator: "/").last!.split(separator: ".").first!).splittingHumanReadableName.joined(separator: " ")
}
let components = typeName
let withoutModule = typeName
.split(separator: ".")
.dropFirst()
.flatMap { $0.split(separator: "_") }
.joined(separator: " ")
.splitBefore(separator: { $0.isUpperCase && !($1?.isUpperCase ?? true) })
.map{ String($0).trimmingCharacters(in: .whitespaces) }
.filter { $0.count > 0 }
.joined(separator: ".")
let components = withoutModule.splittingHumanReadableName
if components.last == "Previews" {
return components.dropLast().joined(separator: " ")
}
Expand Down Expand Up @@ -231,34 +228,3 @@ public enum FindPreviews {
}
}
}

extension Sequence {
func splitBefore(
separator isSeparator: (Iterator.Element, Iterator.Element?) throws -> Bool
) rethrows -> [AnySequence<Iterator.Element>] {
var result: [AnySequence<Iterator.Element>] = []
var subSequence: [Iterator.Element] = []

var iterator = self.makeIterator()
var currentElement = iterator.next()
while let element = currentElement {
let nextElement = iterator.next()
if try isSeparator(element, nextElement) {
if !subSequence.isEmpty {
result.append(AnySequence(subSequence))
}
subSequence = [element]
}
else {
subSequence.append(element)
}
currentElement = nextElement
}
result.append(AnySequence(subSequence))
return result
}
}

extension Character {
var isUpperCase: Bool { return String(self) == String(self).uppercased() }
}
47 changes: 47 additions & 0 deletions Sources/SnapshotPreviewsCore/String+Split.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// String+Split.swift
// SnapshotPreviews
//
// Created by Noah Martin on 1/17/25.
//

extension String {
var splittingHumanReadableName: [String] {
return split(separator: ".").flatMap { $0.split(separator: "_") }
.joined(separator: " ")
.splitBefore(separator: { $0.isUpperCase && !($1?.isUpperCase ?? true) })
.map { String($0).trimmingCharacters(in: .whitespaces) }
.filter { $0.count > 0 }
}
}

extension Sequence {
func splitBefore(
separator isSeparator: (Iterator.Element, Iterator.Element?) throws -> Bool
) rethrows -> [AnySequence<Iterator.Element>] {
var result: [AnySequence<Iterator.Element>] = []
var subSequence: [Iterator.Element] = []

var iterator = self.makeIterator()
var currentElement = iterator.next()
while let element = currentElement {
let nextElement = iterator.next()
if try isSeparator(element, nextElement) {
if !subSequence.isEmpty {
result.append(AnySequence(subSequence))
}
subSequence = [element]
}
else {
subSequence.append(element)
}
currentElement = nextElement
}
result.append(AnySequence(subSequence))
return result
}
}

extension Character {
var isUpperCase: Bool { return String(self) == String(self).uppercased() }
}

0 comments on commit 55198bb

Please sign in to comment.