Help popovers, additional info on collapsed groups

pull/28/head
Pedro Cuenca 2 years ago
parent d0465aa408
commit 424e53274a

@ -65,6 +65,12 @@ struct ControlsView: View {
// TODO: make this computed, and observable, and easy to read // TODO: make this computed, and observable, and easy to read
@State private var mustShowSafetyCheckerDisclaimer = false @State private var mustShowSafetyCheckerDisclaimer = false
@State private var showModelsHelp = false
@State private var showPromptsHelp = false
@State private var showGuidanceHelp = false
@State private var showStepsHelp = false
@State private var showSeedHelp = false
func updateSafetyCheckerState() { func updateSafetyCheckerState() {
mustShowSafetyCheckerDisclaimer = generation.disableSafety && !Settings.shared.safetyCheckerDisclaimerShown mustShowSafetyCheckerDisclaimer = generation.disableSafety && !Settings.shared.safetyCheckerDisclaimerShown
} }
@ -132,9 +138,23 @@ struct ControlsView: View {
modelDidChange(model: model) modelDidChange(model: model)
} }
} label: { } label: {
Label("Model from Hub", systemImage: "cpu").foregroundColor(.secondary) HStack {
Label("Model from Hub", systemImage: "cpu").foregroundColor(.secondary)
Spacer()
if disclosedModel {
Button {
showModelsHelp.toggle()
} label: {
Image(systemName: "info.circle")
}
.buttonStyle(.plain)
// Or maybe use .sheet instead
.sheet(isPresented: $showModelsHelp) {
modelsHelp($showModelsHelp)
}
}
}.foregroundColor(.secondary)
} }
Divider() Divider()
DisclosureGroup(isExpanded: $disclosedPrompt) { DisclosureGroup(isExpanded: $disclosedPrompt) {
@ -148,19 +168,51 @@ struct ControlsView: View {
.textFieldStyle(.squareBorder) .textFieldStyle(.squareBorder)
}.padding(.leading, 10) }.padding(.leading, 10)
} label: { } label: {
Label("Prompts", systemImage: "text.quote").foregroundColor(.secondary) HStack {
Label("Prompts", systemImage: "text.quote").foregroundColor(.secondary)
Spacer()
if disclosedPrompt {
Button {
showPromptsHelp.toggle()
} label: {
Image(systemName: "info.circle")
}
.buttonStyle(.plain)
// Or maybe use .sheet instead
.popover(isPresented: $showPromptsHelp, arrowEdge: .trailing) {
promptsHelp($showPromptsHelp)
}
}
}.foregroundColor(.secondary)
} }
Divider() Divider()
let guidanceScaleValue = generation.guidanceScale.formatted("%.1f")
DisclosureGroup(isExpanded: $disclosedGuidance) { DisclosureGroup(isExpanded: $disclosedGuidance) {
CompactSlider(value: $generation.guidanceScale, in: 0...20, step: 0.5) { CompactSlider(value: $generation.guidanceScale, in: 0...20, step: 0.5) {
Text("Guidance Scale") Text("Guidance Scale")
Spacer() Spacer()
Text(generation.guidanceScale.formatted("%.1f")) Text(guidanceScaleValue)
}.padding(.leading, 10) }.padding(.leading, 10)
} label: { } label: {
Label("Guidance Scale", systemImage: "scalemass").foregroundColor(.secondary) HStack {
Label("Guidance Scale", systemImage: "scalemass").foregroundColor(.secondary)
Spacer()
if disclosedGuidance {
Button {
showGuidanceHelp.toggle()
} label: {
Image(systemName: "info.circle")
}
.buttonStyle(.plain)
// Or maybe use .sheet instead
.popover(isPresented: $showGuidanceHelp, arrowEdge: .trailing) {
guidanceHelp($showGuidanceHelp)
}
} else {
Text(guidanceScaleValue)
}
}.foregroundColor(.secondary)
} }
Divider() Divider()
@ -171,7 +223,23 @@ struct ControlsView: View {
Text("\(Int(generation.steps))") Text("\(Int(generation.steps))")
}.padding(.leading, 10) }.padding(.leading, 10)
} label: { } label: {
Label("Step count", systemImage: "square.3.layers.3d.down.left").foregroundColor(.secondary) HStack {
Label("Step count", systemImage: "square.3.layers.3d.down.left").foregroundColor(.secondary)
Spacer()
if disclosedSteps {
Button {
showStepsHelp.toggle()
} label: {
Image(systemName: "info.circle")
}
.buttonStyle(.plain)
.popover(isPresented: $showStepsHelp, arrowEdge: .trailing) {
stepsHelp($showStepsHelp)
}
} else {
Text("\(Int(generation.steps))")
}
}.foregroundColor(.secondary)
} }
Divider() Divider()
@ -183,7 +251,23 @@ struct ControlsView: View {
Text("\(Int(generation.seed))") Text("\(Int(generation.seed))")
}.padding(.leading, 10) }.padding(.leading, 10)
} label: { } label: {
Label("Seed", systemImage: "leaf").foregroundColor(.secondary) HStack {
Label("Seed", systemImage: "leaf").foregroundColor(.secondary)
Spacer()
if disclosedSeed {
Button {
showSeedHelp.toggle()
} label: {
Image(systemName: "info.circle")
}
.buttonStyle(.plain)
.popover(isPresented: $showSeedHelp, arrowEdge: .trailing) {
seedHelp($showSeedHelp)
}
} else {
Text("\(Int(generation.seed))")
}
}.foregroundColor(.secondary)
} }
} }
} }
@ -224,4 +308,3 @@ struct ControlsView: View {
} }
} }
} }

@ -0,0 +1,125 @@
//
// HelpContent.swift
// Diffusion-macOS
//
// Created by Pedro Cuenca on 7/2/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import SwiftUI
func helpContent(title: String, description: Text, showing: Binding<Bool>, width: Double = 400) -> some View {
VStack {
Text(title)
.font(.title3)
.padding(.top, 10)
.padding(.all, 5)
description
.lineLimit(nil)
.padding(.bottom, 5)
.padding([.leading, .trailing], 15)
Button {
showing.wrappedValue.toggle()
} label: {
Text("Dismiss").frame(maxWidth: 200)
}
.padding(.bottom)
}
.frame(minWidth: width, idealWidth: width, maxWidth: width)
}
func helpContent(title: String, description: String, showing: Binding<Bool>, width: Double = 400) -> some View {
helpContent(title: title, description: Text(description), showing: showing)
}
func helpContent(title: String, description: AttributedString, showing: Binding<Bool>, width: Double = 400) -> some View {
helpContent(title: title, description: Text(description), showing: showing)
}
func modelsHelp(_ showing: Binding<Bool>) -> some View {
let description = try! AttributedString(markdown:
"""
Diffusers launches with a set of 5 models that can be downloaded from the Hugging Face Hub:
**Stable Diffusion 1.4**
This is the original Stable Diffusion model that changed the landscape of AI image generation.
**Stable Diffusion 1.5**
Same architecture as 1.4, but trained on additional images with a focus on aesthetics.
**Stable Diffusion 2**
Improved model, heavily retrained on millions of additional images.
**Stable Diffusion 2.1**
The last reference in the Stable Diffusion family. Works great with _negative prompts_.
OFA small v0
This is a special so-called _distilled_ model, half the size of the others. It runs faster and requires less RAM, try it out if you find generation slow!
""", options: AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace))
return helpContent(title: "Available Models", description: description, showing: showing, width: 600)
}
func promptsHelp(_ showing: Binding<Bool>) -> some View {
let description = try! AttributedString(markdown:
"""
**Prompt** is the description of what you want, and **negative prompt** is what you _don't want_.
Use the negative prompt to tweak a previous generation (by removing unwanted items), or to provide hints for the model.
Many people like to use negative prompts such as "ugly, bad quality" to make the model try harder. \
Or consider excluding terms like "3d" or "realistic" if you're after particular drawing styles.
""", options: AttributedString.MarkdownParsingOptions(interpretedSyntax: .inlineOnlyPreservingWhitespace))
return helpContent(title: "Prompt and Negative Prompt", description: description, showing: showing, width: 600)
}
func guidanceHelp(_ showing: Binding<Bool>) -> some View {
let description =
"""
Indicates how much the image should resemble the prompt.
Low values produce more varied results, while excessively high ones \
may result in image artifacts such as posterization.
Values between 7 and 10 are usually good choices, but they affect \
differently to different models.
Feel free to experiment!
"""
return helpContent(title: "Guidance Scale", description: description, showing: showing)
}
func stepsHelp(_ showing: Binding<Bool>) -> some View {
let description =
"""
How many times to go through the diffusion process.
Quality increases the more steps you choose, but marginal improvements \
get increasingly smaller.
🧨 Diffusers currently uses the super efficient DPM Solver scheduler, \
which produces great results in just 20 or 25 steps 🤯
"""
return helpContent(title: "Inference Steps", description: description, showing: showing)
}
func seedHelp(_ showing: Binding<Bool>) -> some View {
let description =
"""
This is a number that allows you to reproduce a previous generation.
Use it like this: select a seed and write a prompt, then generate an image. \
Next, maybe add a negative prompt or tweak the prompt slightly, and see how the result changes. \
Rinse and repeat until you are satisfied, or select a new seed to start over.
If you select -1, a random seed will be chosen for you.
"""
return helpContent(title: "Generation Seed", description: description, showing: showing)
}

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
EB067F872992E561004D1AD9 /* HelpContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB067F862992E561004D1AD9 /* HelpContent.swift */; };
EB33A51D2954D89F00B16357 /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = EB33A51C2954D89F00B16357 /* StableDiffusion */; }; EB33A51D2954D89F00B16357 /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = EB33A51C2954D89F00B16357 /* StableDiffusion */; };
EBB5BA5329425BEE003A2A5B /* PipelineLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */; }; EBB5BA5329425BEE003A2A5B /* PipelineLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */; };
EBB5BA5829425E17003A2A5B /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = EBB5BA5729425E17003A2A5B /* Path */; }; EBB5BA5829425E17003A2A5B /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = EBB5BA5729425E17003A2A5B /* Path */; };
@ -61,6 +62,7 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
EB067F862992E561004D1AD9 /* HelpContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpContent.swift; sourceTree = "<group>"; };
EB33A51E2954E1BC00B16357 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; EB33A51E2954E1BC00B16357 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineLoader.swift; sourceTree = "<group>"; }; EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineLoader.swift; sourceTree = "<group>"; };
EBB5BA5929426E06003A2A5B /* Downloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; }; EBB5BA5929426E06003A2A5B /* Downloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; };
@ -244,6 +246,7 @@
EBDD7DBB2977FFB300C1C4B2 /* GeneratedImageView.swift */, EBDD7DBB2977FFB300C1C4B2 /* GeneratedImageView.swift */,
F1552030297109C300DC009B /* ControlsView.swift */, F1552030297109C300DC009B /* ControlsView.swift */,
F155203329710B3600DC009B /* StatusView.swift */, F155203329710B3600DC009B /* StatusView.swift */,
EB067F862992E561004D1AD9 /* HelpContent.swift */,
F155202C2971093400DC009B /* Diffusion_macOS.entitlements */, F155202C2971093400DC009B /* Diffusion_macOS.entitlements */,
F15520292971093400DC009B /* Preview Content */, F15520292971093400DC009B /* Preview Content */,
); );
@ -472,6 +475,7 @@
EBDD7DAA29731F6C00C1C4B2 /* Pipeline.swift in Sources */, EBDD7DAA29731F6C00C1C4B2 /* Pipeline.swift in Sources */,
F15520262971093300DC009B /* ContentView.swift in Sources */, F15520262971093300DC009B /* ContentView.swift in Sources */,
EBDD7DB92976AAFE00C1C4B2 /* State.swift in Sources */, EBDD7DB92976AAFE00C1C4B2 /* State.swift in Sources */,
EB067F872992E561004D1AD9 /* HelpContent.swift in Sources */,
EBDD7DB42973200200C1C4B2 /* Utils.swift in Sources */, EBDD7DB42973200200C1C4B2 /* Utils.swift in Sources */,
F1552031297109C300DC009B /* ControlsView.swift in Sources */, F1552031297109C300DC009B /* ControlsView.swift in Sources */,
EBDD7DB62973206600C1C4B2 /* Downloader.swift in Sources */, EBDD7DB62973206600C1C4B2 /* Downloader.swift in Sources */,

Loading…
Cancel
Save