diff --git a/Montana-iOS/Montana Messenger/Montana Messenger/HomeFeedView.swift b/Montana-iOS/Montana Messenger/Montana Messenger/HomeFeedView.swift deleted file mode 100644 index f3f2edf..0000000 --- a/Montana-iOS/Montana Messenger/Montana Messenger/HomeFeedView.swift +++ /dev/null @@ -1,222 +0,0 @@ -import SwiftUI -import Combine - -struct FeedPost: Identifiable, Hashable { - let id = UUID() - let author: String - let handle: String - let timeAgo: String - let body: String - let replies: Int - let reposts: Int - let likes: Int -} - -@MainActor -final class FeedStore: ObservableObject { - static let shared = FeedStore() - @Published var posts: [FeedPost] = [ - FeedPost(author: "Алик Монтана", handle: "@alik", timeAgo: "2м", - body: "Запустили генезис в трёх городах: мос, фра, зел. Время идёт честно.", - replies: 12, reposts: 4, likes: 87), - FeedPost(author: "Юнона", handle: "@junona", timeAgo: "18м", - body: "Никто не читает твои сообщения. Никто не знает, кто ты. Это нормально.", - replies: 3, reposts: 22, likes: 154), - FeedPost(author: "Frankfurt Node", handle: "@fra", timeAgo: "1ч", - body: "Окно 2891844 закрыто. VDF подтверждён. Якорь установлен.", - replies: 0, reposts: 1, likes: 9), - FeedPost(author: "Helsinki Node", handle: "@zel", timeAgo: "3ч", - body: "Reality маска работает. Трафик неотличим от обычного TLS.", - replies: 5, reposts: 11, likes: 42), - FeedPost(author: "Moscow Node", handle: "@mos", timeAgo: "5ч", - body: "efir.org перешёл на :8443 — :443 теперь у Xray. Всё стабильно.", - replies: 2, reposts: 3, likes: 18), - ] - - func publish(_ text: String) { - let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty else { return } - posts.insert(FeedPost(author: "Алик Монтана", handle: "@alik", timeAgo: "сейчас", - body: trimmed, replies: 0, reposts: 0, likes: 0), at: 0) - } -} - -struct HomeFeedView: View { - @StateObject private var store = FeedStore.shared - @State private var composing = false - - var body: some View { - NavigationStack { - ZStack(alignment: .bottomTrailing) { - ScrollView { - LazyVStack(spacing: 0) { - FeedHeader().padding(.top, ClaudeTheme.Spacing.sm) - ForEach(store.posts) { post in - PostRow(post: post) - Rectangle() - .fill(ClaudeTheme.Palette.divider) - .frame(height: 0.5) - .padding(.leading, 76) - } - } - } - .claudeBackground() - - Button { composing = true } label: { - Image(systemName: "square.and.pencil") - .font(.system(size: 22, weight: .medium)) - .foregroundStyle(ClaudeTheme.Palette.bubbleOutText) - .frame(width: 56, height: 56) - .background(Circle().fill(ClaudeTheme.Palette.goldGradient)) - .overlay(Circle().strokeBorder(ClaudeTheme.Palette.goldBright.opacity(0.5), lineWidth: 0.5)) - .shadow(color: ClaudeTheme.Palette.gold.opacity(0.45), radius: 16, y: 4) - } - .padding(.trailing, ClaudeTheme.Spacing.lg) - .padding(.bottom, ClaudeTheme.Spacing.lg) - } - .navigationTitle("Эфир") - .navigationBarTitleDisplayMode(.inline) - .sheet(isPresented: $composing) { - ComposePostView { text in - store.publish(text) - } - } - } - } -} - -private struct FeedHeader: View { - var body: some View { - HStack(spacing: 12) { - Text("Эфир") - .font(.system(size: 32, weight: .bold, design: .serif)) - .foregroundStyle(ClaudeTheme.Palette.goldGradient) - Spacer() - Image(systemName: "sparkles") - .font(.system(size: 18)) - .foregroundStyle(ClaudeTheme.Palette.gold.opacity(0.6)) - } - .padding(.horizontal, ClaudeTheme.Spacing.lg) - .padding(.bottom, 4) - } -} - -private struct PostRow: View { - let post: FeedPost - - var body: some View { - HStack(alignment: .top, spacing: ClaudeTheme.Spacing.md) { - AvatarView(name: post.author, size: 44) - - VStack(alignment: .leading, spacing: 6) { - HStack(spacing: 6) { - Text(post.author) - .font(ClaudeTheme.Typography.headline) - .foregroundStyle(ClaudeTheme.Palette.textPrimary) - Text(post.handle) - .font(ClaudeTheme.Typography.caption) - .foregroundStyle(ClaudeTheme.Palette.textTertiary) - Text("·").foregroundStyle(ClaudeTheme.Palette.textTertiary) - Text(post.timeAgo) - .font(ClaudeTheme.Typography.caption) - .foregroundStyle(ClaudeTheme.Palette.textTertiary) - Spacer() - } - - Text(post.body) - .font(ClaudeTheme.Typography.body) - .foregroundStyle(ClaudeTheme.Palette.textPrimary) - .fixedSize(horizontal: false, vertical: true) - - HStack(spacing: ClaudeTheme.Spacing.xl) { - PostAction(icon: "bubble.left", count: post.replies) - PostAction(icon: "arrow.2.squarepath", count: post.reposts) - PostAction(icon: "heart", count: post.likes) - Spacer() - Image(systemName: "square.and.arrow.up") - .font(.system(size: 14)) - .foregroundStyle(ClaudeTheme.Palette.textTertiary) - } - .padding(.top, 4) - } - } - .padding(.horizontal, ClaudeTheme.Spacing.lg) - .padding(.vertical, ClaudeTheme.Spacing.md) - } -} - -private struct PostAction: View { - let icon: String - let count: Int - var body: some View { - HStack(spacing: 4) { - Image(systemName: icon).font(.system(size: 14)) - if count > 0 { Text("\(count)").font(ClaudeTheme.Typography.caption) } - } - .foregroundStyle(ClaudeTheme.Palette.textTertiary) - } -} - -private struct ComposePostView: View { - @Environment(\.dismiss) private var dismiss - let onPublish: (String) -> Void - @State private var text: String = "" - @FocusState private var focused: Bool - - var body: some View { - NavigationStack { - VStack(alignment: .leading, spacing: 0) { - HStack(alignment: .top, spacing: 12) { - AvatarView(name: "Алик Монтана", size: 44) - TextEditor(text: $text) - .font(ClaudeTheme.Typography.body) - .foregroundStyle(ClaudeTheme.Palette.textPrimary) - .scrollContentBackground(.hidden) - .focused($focused) - .overlay(alignment: .topLeading) { - if text.isEmpty { - Text("Что происходит в эфире?") - .font(ClaudeTheme.Typography.body) - .foregroundStyle(ClaudeTheme.Palette.textTertiary) - .padding(.top, 8) - .padding(.leading, 4) - .allowsHitTesting(false) - } - } - } - .padding(ClaudeTheme.Spacing.lg) - Spacer() - } - .claudeBackground() - .navigationTitle("Новый пост") - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .topBarLeading) { - Button("Отмена") { dismiss() } - .foregroundStyle(ClaudeTheme.Palette.textSecondary) - } - ToolbarItem(placement: .topBarTrailing) { - Button { - onPublish(text) - dismiss() - } label: { - Text("Опубликовать") - .font(.system(size: 14, weight: .semibold)) - .foregroundStyle(text.isEmpty - ? ClaudeTheme.Palette.textTertiary - : ClaudeTheme.Palette.bubbleOutText) - .padding(.horizontal, 14) - .padding(.vertical, 6) - .background( - Capsule().fill(text.isEmpty - ? AnyShapeStyle(ClaudeTheme.Palette.surface) - : AnyShapeStyle(ClaudeTheme.Palette.goldGradient)) - ) - } - .disabled(text.isEmpty) - } - } - .onAppear { focused = true } - } - } -}