Files
jarvis/Jervis/Views/Feeds/AddFeedSheet.swift
Kutesir bd632a1592
Some checks are pending
CI / Build · Debug (push) Waiting to run
CI / Build · Release (push) Waiting to run
rename: Jarvis -> Jervis target, scheme, and folder throughout
The bundle-ID and display-name renames weren't enough — the actual
Xcode target/product name was still "Jarvis", which drives CFBundleName,
Xcode's Organizer archive list, the .xcodeproj filename, and the scheme
name. Renamed all the way through:

- project.yml: top-level name, target key, PRODUCT_NAME, source/info paths
- Jarvis/ -> Jervis/ (source folder, git-tracked as renames, no content
  diffs on the moved files)
- .gitignore, CI workflows, README, CONTRIBUTING: Jarvis.xcodeproj /
  scheme Jarvis -> Jervis.xcodeproj / scheme Jervis

Verified: xcodebuild -scheme Jervis succeeds, produces Jervis.app,
CFBundleName/CFBundleExecutable/CFBundleDisplayName all read "Jervis".
CFBundleIdentifier intentionally stays com.kisani.jarvis (per prior
decision — bundle ID isn't user-facing anywhere including Organizer).

Swift type names (JarvisApp, JarvisWordmark, etc.) and the Gitea repo
name/URL are unchanged — pure internal source identifiers, not user or
developer-facing product identity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 03:49:31 +03:00

114 lines
4.3 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// AddFeedSheet.swift
// Jarvis add a new RSS feed: URL + name + confirm.
import SwiftUI
struct AddFeedSheet: View {
/// Returns true on success.
let onAdd: (String, String) async -> Bool
@Environment(\.dismiss) private var dismiss
@State private var url = ""
@State private var name = ""
@State private var isSubmitting = false
@State private var errorMessage: String?
private var canSubmit: Bool {
!url.trimmingCharacters(in: .whitespaces).isEmpty &&
!name.trimmingCharacters(in: .whitespaces).isEmpty &&
!isSubmitting
}
var body: some View {
ZStack {
Palette.background.ignoresSafeArea()
VStack(alignment: .leading, spacing: 0) {
HStack {
Text("Add feed")
.font(.system(size: 22, weight: .heavy))
.foregroundStyle(Palette.primaryText)
Spacer()
Button { dismiss() } label: {
Image(systemName: "xmark")
.font(.system(size: 15, weight: .bold))
.foregroundStyle(Color(hex: "888888"))
.frame(width: 44, height: 44)
}
}
.padding(.top, 8)
field(label: "FEED URL", text: $url,
placeholder: "https://example.com/rss",
mono: true, keyboard: .URL)
.padding(.top, 12)
field(label: "DISPLAY NAME", text: $name,
placeholder: "Example News",
mono: false, keyboard: .default)
.padding(.top, 16)
if let errorMessage {
Text(errorMessage)
.font(.system(size: 13))
.foregroundStyle(Color(hex: "C25555"))
.padding(.top, 14)
}
Button {
Task { await submit() }
} label: {
HStack {
Spacer()
if isSubmitting {
ProgressView().tint(.black)
} else {
Text("Add feed").font(.system(size: 16, weight: .bold)).foregroundStyle(.black)
}
Spacer()
}
.frame(height: 52)
.background(canSubmit ? Palette.orange : Palette.surface2)
.clipShape(RoundedRectangle(cornerRadius: 14))
}
.disabled(!canSubmit)
.padding(.top, 28)
Spacer()
}
.padding(.horizontal, 20)
}
.presentationDetents([.medium])
.presentationDragIndicator(.visible)
}
private func field(label: String, text: Binding<String>, placeholder: String,
mono: Bool, keyboard: UIKeyboardType) -> some View {
VStack(alignment: .leading, spacing: 8) {
Text(label)
.font(.system(size: 10, weight: .bold, design: .monospaced))
.kerning(0.8)
.foregroundStyle(Palette.tertiaryText)
TextField("", text: text,
prompt: Text(placeholder).foregroundColor(Palette.mutedText))
.font(.system(size: 15, weight: .regular, design: mono ? .monospaced : .default))
.foregroundStyle(mono ? Palette.orange : .white)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
.keyboardType(keyboard)
.padding(14)
.background(Palette.surface)
.overlay(RoundedRectangle(cornerRadius: 12).stroke(Palette.surface2, lineWidth: 1))
.clipShape(RoundedRectangle(cornerRadius: 12))
}
}
private func submit() async {
isSubmitting = true
errorMessage = nil
let ok = await onAdd(url.trimmingCharacters(in: .whitespaces),
name.trimmingCharacters(in: .whitespaces))
isSubmitting = false
if ok { dismiss() } else { errorMessage = "Couldnt add feed. Check the URL and try again." }
}
}