Skip to content

Instantly share code, notes, and snippets.

@adityadaniel
Last active February 12, 2026 03:44
Show Gist options
  • Select an option

  • Save adityadaniel/35d5643db2f84f571c0573f820da117d to your computer and use it in GitHub Desktop.

Select an option

Save adityadaniel/35d5643db2f84f571c0573f820da117d to your computer and use it in GitHub Desktop.
NewPostView
enum CategoryType: String, Codable, CaseIterable {
case post
case event
}
enum EmotionType: String, Codable, CaseIterable {
case happy
case lovely
case neutral
case sad
case angry
case drowning
var emoji: String {
switch self {
case .happy: return "😄"
case .sad: return "😢"
case .angry: return "😠"
case .drowning: return "🌊"
case .lovely: return "💖"
case .neutral: return "🤔"
}
}
var title: String {
switch self {
case .happy: return "Happy"
case .sad: return "Sad"
case .angry: return "Angry"
case .drowning: return "Drowning"
case .lovely: return "Lovely"
case .neutral: return "Neutral"
}
}
}
struct PostModel {
var id = UUID()
var category: CategoryType
var title: String
var image: UIImage?
var emotion: EmotionType?
}
//
// NewPostView.swift
// Thunderosaurus
//
// Created by Ivan on 11/02/26.
//
import SwiftUI
import PhotosUI
struct PostInputView: View {
@Binding var content: String
var body: some View {
Section("What's this post about") {
TextEditor(text: $content)
.frame(height: 150)
}
}
}
struct NewPostView: View {
@EnvironmentObject private var viewModel: ViewModel
@Environment(\.dismiss) private var dismiss
@State private var selectedCategory: CategoryType = .post
@State private var content: String = ""
@State private var photosItem: PhotosPickerItem? = nil
@State private var selectedImage: UIImage? = nil
@State private var selectedEmotion: EmotionType = .happy
@State private var isSending: Bool = false
@EnvironmentObject private var viewmodel: ViewModel
var body: some View {
Form {
Section {
Picker("Category", selection: self.$selectedCategory) {
ForEach(CategoryType.allCases, id: \.rawValue) { type in
Text(type.rawValue.capitalized)
.tag(type)
}
}
.pickerStyle(.menu)
}
PostInputView(content: $content)
Section {
if let image = self.selectedImage {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxHeight: 200)
.padding(.vertical)
.clipShape(RoundedRectangle(cornerRadius: 12))
} else {
PhotosPicker(selection: self.$photosItem) {
Label("Add new photo", systemImage: "photo.badge.plus")
}
}
}
Section("Emotion") {
let columns = Array(repeating: GridItem(.flexible(), spacing: 8), count: 3)
LazyVGrid(columns: columns, spacing: 8) {
ForEach(EmotionType.allCases, id: \.self) { emotionType in
Button {
withAnimation { self.selectedEmotion = emotionType }
} label: {
HStack(spacing: 6) {
Text(emotionType.emoji)
Text(emotionType.title)
.font(.subheadline)
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 8)
.background(
self.selectedEmotion == emotionType
? Color.accentColor.opacity(0.18)
: Color.clear
)
.overlay(
Capsule()
.stroke(
self.selectedEmotion == emotionType
? Color.accentColor
: Color.secondary.opacity(0.4),
lineWidth: 1
)
)
.clipShape(Capsule())
}
.buttonStyle(.plain)
.accessibilityLabel(emotionType.title)
.accessibilityValue(
self.selectedEmotion == emotionType ? "Selected" : ""
)
}
}
.padding(.vertical, 4)
}
Section {
Button {
self.sendPost()
} label: {
HStack(spacing: 8) {
if self.isSending {
ProgressView()
.progressViewStyle(.circular)
}
Text(self.isSending ? "Sending..." : "Add")
}
}
.buttonStyle(.glassProminent)
.controlSize(.large)
.buttonSizing(.flexible)
.tint(self.isSending ? .gray : .accentColor)
.disabled(self.isSending)
}
}
.onChange(of: self.photosItem, { oldValue, newValue in
if let item = newValue {
item.loadTransferable(type: Data.self) { photoData in
switch photoData {
case .success(let data):
if let data, let uiImage = UIImage(data: data) {
self.selectedImage = uiImage
} else {
print("error loading photo")
}
case .failure(let error):
print("error loading photo, \(error)")
}
}
}
})
.navigationTitle("Add new post")
.toolbarTitleDisplayMode(.inlineLarge)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Cancel") {
self.dismiss()
}
}
}
}
private func sendPost() {
if self.isSending {
return
}
self.isSending = true
Task {
let delay = UInt64.random(in: 800_000_000...2_200_000_000)
try? await Task.sleep(nanoseconds: delay)
let post = PostModel(
category: self.selectedCategory,
title: self.content,
image: self.selectedImage,
emotion: self.selectedEmotion
)
self.viewModel.addPost(post)
self.isSending = false
self.dismiss()
}
}
}
#Preview {
NavigationStack {
NewPostView()
}
.environmentObject(ViewModel())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment