ура перехват крашей и информация об устройстве йес
This commit is contained in:
parent
a8401d6b19
commit
f64df7c5e5
77
MobileMkch/CrashHandler.swift
Normal file
77
MobileMkch/CrashHandler.swift
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import SwiftUI
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class CrashHandler: ObservableObject {
|
||||||
|
static let shared = CrashHandler()
|
||||||
|
@Published var hasCrashed = false
|
||||||
|
@Published var crashMessage = ""
|
||||||
|
|
||||||
|
private init() {
|
||||||
|
setupCrashHandler()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupCrashHandler() {
|
||||||
|
NSSetUncaughtExceptionHandler { exception in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
CrashHandler.shared.hasCrashed = true
|
||||||
|
CrashHandler.shared.crashMessage = exception.reason ?? "idk че произошло\nПерезайди и скинь скрин из настроек (самый низ) (ну и че ты делал до краша)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGABRT) { _ in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
CrashHandler.shared.hasCrashed = true
|
||||||
|
CrashHandler.shared.crashMessage = "Похоже... приложение упало..? Ты попал на ТЕРРИТОРИИ SIGABRT\nПерезайди и скинь скрин из настроек (самый низ)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func triggerTestCrash() {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
|
self.hasCrashed = true
|
||||||
|
self.crashMessage = "Похоже... приложение упало..? Ты попал на НЕИЗВЕДАННЫЕ ТЕРРИТОРИИ\nПерезайди и скинь скрин из настроек (самый низ)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CrashScreen: View {
|
||||||
|
@ObservedObject var crashHandler = CrashHandler.shared
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 30) {
|
||||||
|
Image(systemName: "exclamationmark.triangle.fill")
|
||||||
|
.font(.system(size: 60))
|
||||||
|
.foregroundColor(.red)
|
||||||
|
|
||||||
|
Text("Произошла ошибка")
|
||||||
|
.font(.largeTitle)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
|
||||||
|
Text(crashHandler.crashMessage)
|
||||||
|
.font(.body)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
VStack(spacing: 15) {
|
||||||
|
Text("Рекомендуется:")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
Text("Закрыть приложение")
|
||||||
|
Text("Открыть заново")
|
||||||
|
Text("Если проблема повторяется - переустановить")
|
||||||
|
}
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button("окек") {
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderedProminent)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(Color(.systemBackground))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,9 +11,14 @@ import SwiftUI
|
|||||||
struct MobileMkchApp: App {
|
struct MobileMkchApp: App {
|
||||||
@StateObject private var settings = Settings()
|
@StateObject private var settings = Settings()
|
||||||
@StateObject private var apiClient = APIClient()
|
@StateObject private var apiClient = APIClient()
|
||||||
|
@StateObject private var crashHandler = CrashHandler.shared
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
|
Group {
|
||||||
|
if crashHandler.hasCrashed {
|
||||||
|
CrashScreen()
|
||||||
|
} else {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
BoardsView()
|
BoardsView()
|
||||||
.environmentObject(settings)
|
.environmentObject(settings)
|
||||||
@ -23,3 +28,5 @@ struct MobileMkchApp: App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
|
import Darwin
|
||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@EnvironmentObject var settings: Settings
|
@EnvironmentObject var settings: Settings
|
||||||
@ -12,6 +13,8 @@ struct SettingsView: View {
|
|||||||
@State private var testPasscodeResult: String?
|
@State private var testPasscodeResult: String?
|
||||||
@State private var isTestingKey = false
|
@State private var isTestingKey = false
|
||||||
@State private var isTestingPasscode = false
|
@State private var isTestingPasscode = false
|
||||||
|
@State private var debugTapCount = 0
|
||||||
|
@State private var showingDebugMenu = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
@ -140,6 +143,24 @@ struct SettingsView: View {
|
|||||||
showingInfo = true
|
showingInfo = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Section("Информация об устройстве") {
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
Text("Устройство: \(getDeviceModel())")
|
||||||
|
Text("Система: \(UIDevice.current.systemName) \(UIDevice.current.systemVersion)")
|
||||||
|
Text("Тип: \(UIDevice.current.name.isEmpty ? "Не удалось определить, увы" : UIDevice.current.name)")
|
||||||
|
Text("Идентификатор: \(UIDevice.current.identifierForVendor?.uuidString ?? "Неизвестно")")
|
||||||
|
}
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.onTapGesture {
|
||||||
|
debugTapCount += 1
|
||||||
|
if debugTapCount >= 5 {
|
||||||
|
showingDebugMenu = true
|
||||||
|
debugTapCount = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Настройки")
|
.navigationTitle("Настройки")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
@ -153,6 +174,9 @@ struct SettingsView: View {
|
|||||||
.sheet(isPresented: $showingAbout) {
|
.sheet(isPresented: $showingAbout) {
|
||||||
AboutView()
|
AboutView()
|
||||||
}
|
}
|
||||||
|
.sheet(isPresented: $showingDebugMenu) {
|
||||||
|
DebugMenuView()
|
||||||
|
}
|
||||||
.alert("Информация о НЕОЖИДАНЫХ проблемах", isPresented: $showingInfo) {
|
.alert("Информация о НЕОЖИДАНЫХ проблемах", isPresented: $showingInfo) {
|
||||||
Button("Закрыть") { }
|
Button("Закрыть") { }
|
||||||
} message: {
|
} message: {
|
||||||
@ -198,6 +222,18 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func getDeviceModel() -> String {
|
||||||
|
var systemInfo = utsname()
|
||||||
|
uname(&systemInfo)
|
||||||
|
let machineMirror = Mirror(reflecting: systemInfo.machine)
|
||||||
|
let identifier = machineMirror.children.reduce("") { identifier, element in
|
||||||
|
guard let value = element.value as? Int8, value != 0 else { return identifier }
|
||||||
|
return identifier + String(UnicodeScalar(UInt8(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return identifier
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AboutView: View {
|
struct AboutView: View {
|
||||||
@ -237,6 +273,39 @@ struct AboutView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DebugMenuView: View {
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
VStack(spacing: 20) {
|
||||||
|
Text("Debug Menu")
|
||||||
|
.font(.largeTitle)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
|
||||||
|
VStack(spacing: 15) {
|
||||||
|
Button("Тест краша") {
|
||||||
|
CrashHandler.shared.triggerTestCrash()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderedProminent)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button("Закрыть") {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
.buttonStyle(.bordered)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.navigationTitle("Debug")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
SettingsView()
|
SettingsView()
|
||||||
.environmentObject(Settings())
|
.environmentObject(Settings())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user