From 08119cd2092244a8242368eadb5c2d245e54970d Mon Sep 17 00:00:00 2001 From: Lain Iwakura Date: Thu, 7 Aug 2025 13:36:57 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B8=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D0=B8=D0=B8=20=D0=BF=D0=BE=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D0=B8=D0=B2=D0=B5=D0=B5=20=D0=B8=D0=B1=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D1=88=D0=BC=D0=B0=D1=80=20=D0=BA=D0=B0=D0=BA=D0=BE=D0=B5?= =?UTF-8?q?=20=D1=83=D1=80=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=BE=20=D0=B1?= =?UTF-8?q?=D1=8B=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MobileMkch/AddCommentView.swift | 149 +++++++++++++++++--------- MobileMkch/CreateThreadView.swift | 172 ++++++++++++++++++++---------- 2 files changed, 214 insertions(+), 107 deletions(-) diff --git a/MobileMkch/AddCommentView.swift b/MobileMkch/AddCommentView.swift index eb9fc57..95dcf8a 100644 --- a/MobileMkch/AddCommentView.swift +++ b/MobileMkch/AddCommentView.swift @@ -11,77 +11,120 @@ struct AddCommentView: View { @State private var isLoading = false @State private var errorMessage: String? @State private var showingSuccess = false + @FocusState private var isTextFocused: Bool var body: some View { NavigationView { - Form { - Section { - TextField("Текст комментария", text: $text) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .frame(minHeight: 100) - } - .ignoresSafeArea(.keyboard, edges: .bottom) - - Section { - if !settings.passcode.isEmpty { + VStack(spacing: 0) { + VStack(spacing: 16) { + VStack(alignment: .leading, spacing: 8) { HStack { - Image(systemName: "checkmark.circle.fill") - .foregroundColor(.green) - Text("Passcode настроен") - .foregroundColor(.green) + Text("Комментарий") + .font(.headline) + .foregroundColor(.primary) + Spacer() + Text("\(text.count)") + .font(.caption) + .foregroundColor(.secondary) } - } else { + + TextEditor(text: $text) + .focused($isTextFocused) + .frame(minHeight: 120) + .padding(12) + .background(Color(.secondarySystemBackground)) + .cornerRadius(12) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(isTextFocused ? Color.accentColor : Color.clear, lineWidth: 2) + ) + .overlay( + Group { + if text.isEmpty { + HStack { + VStack { + Text("Напишите ваш комментарий...") + .foregroundColor(.secondary) + .padding(.top, 20) + .padding(.leading, 16) + Spacer() + } + Spacer() + } + } + } + ) + } + + HStack(spacing: 8) { + Image(systemName: settings.passcode.isEmpty ? "exclamationmark.triangle.fill" : "checkmark.circle.fill") + .foregroundColor(settings.passcode.isEmpty ? .orange : .green) + + Text(settings.passcode.isEmpty ? "Passcode не настроен" : "Passcode настроен") + .font(.caption) + .foregroundColor(settings.passcode.isEmpty ? .orange : .green) + + Spacer() + } + .padding(.horizontal, 4) + + if let error = errorMessage { HStack { - Image(systemName: "exclamationmark.triangle.fill") - .foregroundColor(.orange) - VStack(alignment: .leading) { - Text("Passcode не настроен") - .foregroundColor(.orange) - Text("Постинг может быть ограничен") - .font(.caption) - .foregroundColor(.secondary) + Image(systemName: "xmark.circle.fill") + .foregroundColor(.red) + Text(error) + .font(.caption) + .foregroundColor(.red) + Spacer() + } + .padding(.horizontal, 4) + } + } + .padding(.horizontal, 20) + .padding(.top, 20) + + Spacer() + + VStack(spacing: 12) { + Button(action: addComment) { + HStack { + if isLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle(tint: .white)) + .scaleEffect(0.8) + } else { + Image(systemName: "plus.circle.fill") } + Text(isLoading ? "Отправка..." : "Добавить комментарий") } + .frame(maxWidth: .infinity) + .frame(height: 50) + .background(text.isEmpty || isLoading ? Color.gray : Color.accentColor) + .foregroundColor(.white) + .cornerRadius(25) + .animation(.easeInOut(duration: 0.2), value: text.isEmpty) } - } - - if let error = errorMessage { - Section { - Text(error) - .foregroundColor(.red) + .disabled(text.isEmpty || isLoading) + + Button("Отмена") { + dismiss() } + .foregroundColor(.secondary) } + .padding(.horizontal, 20) + .padding(.bottom, 20) } - .navigationTitle("Комментарий в тред \(threadId)") + .navigationTitle("Тред \(threadId)") .navigationBarTitleDisplayMode(.inline) - .navigationBarBackButtonHidden(false) - .navigationBarItems( - leading: Button("Отмена") { - dismiss() - }, - trailing: Button("Добавить") { - addComment() - } - .disabled(text.isEmpty || isLoading) - ) - .overlay { - if isLoading { - VStack { - ProgressView() - .progressViewStyle(CircularProgressViewStyle()) - Text("Добавление комментария...") - .foregroundColor(.secondary) - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color(.systemBackground)) - } + .onAppear { + isTextFocused = true } - .alert("Комментарий добавлен", isPresented: $showingSuccess) { + .alert("Успешно!", isPresented: $showingSuccess) { Button("OK") { dismiss() } } message: { - Text("Комментарий успешно добавлен") + Text("Комментарий добавлен") } } } diff --git a/MobileMkch/CreateThreadView.swift b/MobileMkch/CreateThreadView.swift index 1c9db75..0ce8b6b 100644 --- a/MobileMkch/CreateThreadView.swift +++ b/MobileMkch/CreateThreadView.swift @@ -11,79 +11,143 @@ struct CreateThreadView: View { @State private var isLoading = false @State private var errorMessage: String? @State private var showingSuccess = false + @FocusState private var titleFocused: Bool + @FocusState private var textFocused: Bool var body: some View { NavigationView { - Form { - Section { - TextField("Заголовок треда", text: $title) - .textFieldStyle(RoundedBorderTextFieldStyle()) - - TextField("Текст треда", text: $text) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .frame(minHeight: 100) - } - .ignoresSafeArea(.keyboard, edges: .bottom) - - Section { - if !settings.passcode.isEmpty { - HStack { - Image(systemName: "checkmark.circle.fill") - .foregroundColor(.green) - Text("Passcode настроен") - .foregroundColor(.green) - } - } else { - HStack { - Image(systemName: "exclamationmark.triangle.fill") - .foregroundColor(.orange) - VStack(alignment: .leading) { - Text("Passcode не настроен") - .foregroundColor(.orange) - Text("Постинг может быть ограничен") + VStack(spacing: 0) { + ScrollView { + VStack(spacing: 20) { + VStack(alignment: .leading, spacing: 8) { + HStack { + Text("Заголовок") + .font(.headline) + .foregroundColor(.primary) + Spacer() + Text("\(title.count)") .font(.caption) .foregroundColor(.secondary) } + + TextField("Введите заголовок треда", text: $title) + .focused($titleFocused) + .padding(16) + .background(Color(.secondarySystemBackground)) + .cornerRadius(12) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(titleFocused ? Color.accentColor : Color.clear, lineWidth: 2) + ) + } + + VStack(alignment: .leading, spacing: 8) { + HStack { + Text("Содержание") + .font(.headline) + .foregroundColor(.primary) + Spacer() + Text("\(text.count)") + .font(.caption) + .foregroundColor(.secondary) + } + + TextEditor(text: $text) + .focused($textFocused) + .frame(minHeight: 140) + .padding(12) + .background(Color(.secondarySystemBackground)) + .cornerRadius(12) + .overlay( + RoundedRectangle(cornerRadius: 12) + .stroke(textFocused ? Color.accentColor : Color.clear, lineWidth: 2) + ) + .overlay( + Group { + if text.isEmpty { + HStack { + VStack { + Text("Напишите содержание треда...") + .foregroundColor(.secondary) + .padding(.top, 20) + .padding(.leading, 16) + Spacer() + } + Spacer() + } + } + } + ) + } + + HStack(spacing: 8) { + Image(systemName: settings.passcode.isEmpty ? "exclamationmark.triangle.fill" : "checkmark.circle.fill") + .foregroundColor(settings.passcode.isEmpty ? .orange : .green) + + Text(settings.passcode.isEmpty ? "Passcode не настроен" : "Passcode настроен") + .font(.caption) + .foregroundColor(settings.passcode.isEmpty ? .orange : .green) + + Spacer() + } + .padding(.horizontal, 4) + + if let error = errorMessage { + HStack { + Image(systemName: "xmark.circle.fill") + .foregroundColor(.red) + Text(error) + .font(.caption) + .foregroundColor(.red) + Spacer() + } + .padding(.horizontal, 4) } } + .padding(.horizontal, 20) + .padding(.top, 20) } - if let error = errorMessage { - Section { - Text(error) - .foregroundColor(.red) + VStack(spacing: 12) { + Button(action: createThread) { + HStack { + if isLoading { + ProgressView() + .progressViewStyle(CircularProgressViewStyle(tint: .white)) + .scaleEffect(0.8) + } else { + Image(systemName: "plus.circle.fill") + } + Text(isLoading ? "Создание..." : "Создать тред") + } + .frame(maxWidth: .infinity) + .frame(height: 50) + .background(title.isEmpty || text.isEmpty || isLoading ? Color.gray : Color.accentColor) + .foregroundColor(.white) + .cornerRadius(25) + .animation(.easeInOut(duration: 0.2), value: title.isEmpty || text.isEmpty) } + .disabled(title.isEmpty || text.isEmpty || isLoading) + + Button("Отмена") { + dismiss() + } + .foregroundColor(.secondary) } + .padding(.horizontal, 20) + .padding(.bottom, 20) } - .navigationTitle("Создать тред /\(boardCode)/") + .navigationTitle("/\(boardCode)/") .navigationBarTitleDisplayMode(.inline) - .navigationBarItems( - leading: Button("Отмена") { - dismiss() - }, - trailing: Button("Создать") { - createThread() - } - .disabled(title.isEmpty || text.isEmpty || isLoading) - ) - .overlay { - if isLoading { - VStack { - ProgressView() - .progressViewStyle(CircularProgressViewStyle()) - Text("Создание треда...") - .foregroundColor(.secondary) - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color(.systemBackground)) - } + .onAppear { + titleFocused = true } - .alert("Тред создан", isPresented: $showingSuccess) { + .alert("Успешно!", isPresented: $showingSuccess) { Button("OK") { dismiss() } } message: { - Text("Тред успешно создан") + Text("Тред создан") } } }