Skip to content

Commit ac41467

Browse files
Added loading indicator while model is loading, also add a Placeholder (#385)
- Add isLoadingModel state to DiffusionViewModel - Show progress indicator and "Loading..." text during model load - Add first-load info banner in DiffusionModelPickerView - Disable buttons appropriately during loading Co-authored-by: Shubham Malhotra <shubham.malhotra28@gmail.com>
1 parent 3fafd41 commit ac41467

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Diffusion/DiffusionViewModel.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class DiffusionViewModel: ObservableObject {
2222
@Published var downloadProgress: Double = 0.0
2323
@Published var downloadStatus: String = ""
2424

25+
@Published var isLoadingModel = false
26+
2527
@Published var isGenerating = false
2628
@Published var progress: Float = 0.0
2729
@Published var statusMessage: String = "Ready"
@@ -120,9 +122,12 @@ class DiffusionViewModel: ObservableObject {
120122
return
121123
}
122124

125+
isLoadingModel = true
123126
statusMessage = "Loading model..."
124127
errorMessage = nil
125128

129+
defer { isLoadingModel = false }
130+
126131
do {
127132
// App only supports Apple SD 1.5 (CoreML); use .sd15 for configuration
128133
let variant: DiffusionModelVariant = .sd15

examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Diffusion/ImageGenerationView.swift

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,24 @@ struct DiffusionModelPickerView: View {
234234
@ObservedObject var viewModel: DiffusionViewModel
235235
@Binding var isPresented: Bool
236236

237+
private static let firstLoadBannerText = "First load may take 1–2 minutes depending on model size and device performance."
238+
237239
var body: some View {
238240
NavigationView {
239241
VStack(spacing: 0) {
242+
// First-load info banner
243+
HStack(spacing: AppSpacing.small) {
244+
Image(systemName: "clock.badge.checkmark")
245+
.font(.body)
246+
.foregroundStyle(AppColors.primaryAccent)
247+
Text(Self.firstLoadBannerText)
248+
.font(.subheadline)
249+
.foregroundColor(.secondary)
250+
}
251+
.frame(maxWidth: .infinity, alignment: .leading)
252+
.padding()
253+
.background(AppColors.backgroundSecondary)
254+
240255
if viewModel.availableModels.isEmpty {
241256
VStack(spacing: AppSpacing.large) {
242257
Image(systemName: "photo.artframe")
@@ -261,15 +276,24 @@ struct DiffusionModelPickerView: View {
261276
}
262277
Spacer()
263278
if model.isDownloaded {
264-
Button("Load") {
265-
viewModel.selectedModel = model
266-
Task {
267-
await viewModel.loadSelectedModel()
268-
if viewModel.isModelLoaded { isPresented = false }
279+
if viewModel.isLoadingModel && viewModel.selectedModel?.id == model.id {
280+
HStack(spacing: AppSpacing.small) {
281+
ProgressView()
282+
Text("Loading...")
283+
.font(.caption)
284+
.foregroundColor(.secondary)
269285
}
286+
} else {
287+
Button("Load") {
288+
viewModel.selectedModel = model
289+
Task {
290+
await viewModel.loadSelectedModel()
291+
if viewModel.isModelLoaded { isPresented = false }
292+
}
293+
}
294+
.buttonStyle(.borderedProminent)
295+
.disabled(viewModel.isDownloading)
270296
}
271-
.buttonStyle(.borderedProminent)
272-
.disabled(viewModel.isDownloading)
273297
} else {
274298
Button("Download") {
275299
viewModel.selectedModel = model

0 commit comments

Comments
 (0)