Files
stickercloner/StickerCloner/StickerCloner MessagesExtension/AddPackView.swift
T

129 lines
3.0 KiB
Swift

import SwiftUI
struct AddPackView: View {
@State private var urlText = ""
@State private var isLoading = false
@State private var errorMessage: String?
@State private var packs: [SavedPack]
var onPacksChanged: () -> Void
init(onPacksChanged: @escaping () -> Void) {
self.onPacksChanged = onPacksChanged
_packs = State(initialValue: StickerStore.shared.savedPacks)
}
var body: some View {
NavigationView {
List {
Section {
HStack {
TextField("t.me/addstickers/PackName", text: $urlText)
.textContentType(.URL)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
Button {
addPack()
} label: {
if isLoading {
ProgressView()
} else {
Text("Add")
}
}
.disabled(urlText.isEmpty || isLoading)
}
if let errorMessage {
Text(errorMessage)
.foregroundStyle(.red)
.font(.caption)
}
} header: {
Text("Add Sticker Pack")
} footer: {
Text("Paste a Telegram sticker link or pack name.")
}
if !packs.isEmpty {
Section("Saved Packs") {
ForEach(packs, id: \.name) { pack in
HStack {
VStack(alignment: .leading) {
Text(pack.title)
Text("\(pack.stickerCount) stickers")
.font(.caption)
.foregroundStyle(.secondary)
}
Spacer()
}
}
.onDelete(perform: deletePacks)
}
}
}
.navigationTitle("Sticker Packs")
.navigationBarTitleDisplayMode(.inline)
}
}
// MARK: - Actions
private func addPack() {
let name = extractPackName(from: urlText)
guard !name.isEmpty else {
errorMessage = "Could not parse pack name from input."
return
}
isLoading = true
errorMessage = nil
Task {
do {
let response = try await StickerClonerAPI.fetchStickerSet(name: name)
try await StickerStore.shared.addPack(response: response)
packs = StickerStore.shared.savedPacks
urlText = ""
onPacksChanged()
} catch {
errorMessage = error.localizedDescription
}
isLoading = false
}
}
private func deletePacks(at offsets: IndexSet) {
for index in offsets {
StickerStore.shared.removePack(name: packs[index].name)
}
packs = StickerStore.shared.savedPacks
onPacksChanged()
}
private func extractPackName(from input: String) -> String {
let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines)
// Handle full URL: https://t.me/addstickers/PackName
if let url = URL(string: trimmed),
let host = url.host,
host.hasSuffix("t.me") {
let components = url.pathComponents
if let addstickersIndex = components.firstIndex(of: "addstickers"),
addstickersIndex + 1 < components.count {
return components[addstickersIndex + 1]
}
return url.lastPathComponent
}
// Handle bare URL without scheme
if trimmed.contains("t.me/addstickers/") {
return trimmed.components(separatedBy: "t.me/addstickers/").last ?? ""
}
// Treat as bare pack name
return trimmed
}
}