This commit is contained in:
cheykrym 2025-12-10 00:11:53 +03:00
parent da3a46e272
commit bcbbe99d8f
4 changed files with 150 additions and 136 deletions

View File

@ -2243,9 +2243,6 @@
}, },
"Разблокировать" : { "Разблокировать" : {
"comment" : "Unblock confirmation action" "comment" : "Unblock confirmation action"
},
"Размер кэша аватаров на диске." : {
}, },
"Разрешить пересылку сообщений" : { "Разрешить пересылку сообщений" : {
"localizations" : { "localizations" : {

View File

@ -157,6 +157,15 @@ class AvatarCacheService {
func clearCache(forUserId userId: String) { func clearCache(forUserId userId: String) {
guard let directory = cacheDirectory(for: userId) else { return } guard let directory = cacheDirectory(for: userId) else { return }
// Try to delete files inside first, ignoring errors
if let fileUrls = try? fileManager.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil, options: []) {
for fileUrl in fileUrls {
try? fileManager.removeItem(at: fileUrl)
}
}
// Then try to delete the directory itself
try? fileManager.removeItem(at: directory) try? fileManager.removeItem(at: directory)
} }

View File

@ -0,0 +1,141 @@
//
// DataSettingsView.swift
// yobble
//
// Created by cheykrym on 10.12.2025.
//
import SwiftUI
struct DataSettingsView: View {
let currentUserId: String
private let cacheService = AvatarCacheService.shared
@State private var cachedUsers: [CachedUserInfo] = []
@State private var totalCacheSize: Int64 = 0
@State private var showClearAllConfirmation = false
@State private var showClearOthersConfirmation = false
@State private var showClearCurrentConfirmation = false
var body: some View {
Form {
Section(header: Text("Общая информация")) {
HStack {
Text("Общий размер")
Spacer()
Text(format(bytes: totalCacheSize))
.foregroundColor(.secondary)
}
}
Section(header: Text("Массовая отчистка")) {
Button("Очистить кэш текущего пользователя", role: .destructive) {
showClearCurrentConfirmation = true
}
.confirmationDialog(
"Вы уверены, что хотите очистить кэш для текущего пользователя?",
isPresented: $showClearCurrentConfirmation,
titleVisibility: .visible
) {
Button("Очистить", role: .destructive) {
clearCache(for: currentUserId)
}
}
Button("Очистить кэш (кроме текущего)", role: .destructive) {
showClearOthersConfirmation = true
}
.confirmationDialog(
"Вы уверены, что хотите очистить кэш для всех, кроме текущего пользователя?",
isPresented: $showClearOthersConfirmation,
titleVisibility: .visible
) {
Button("Очистить", role: .destructive, action: clearOtherUsersCache)
}
Button("Очистить весь кэш", role: .destructive) {
showClearAllConfirmation = true
}
.confirmationDialog(
"Вы уверены, что хотите очистить весь кэш аватаров? Это действие необратимо.",
isPresented: $showClearAllConfirmation,
titleVisibility: .visible
) {
Button("Очистить всё", role: .destructive, action: clearAllCache)
}
}
Section(header: Text("Кэш по пользователям")) {
if cachedUsers.isEmpty {
Text("Кэш пуст")
.foregroundColor(.secondary)
} else {
ForEach(cachedUsers) { user in
HStack {
VStack(alignment: .leading) {
Text(user.id)
.font(.system(.body, design: .monospaced))
.lineLimit(1)
.truncationMode(.middle)
if user.id == currentUserId {
Text("Текущий")
.font(.caption)
.foregroundColor(.accentColor)
}
}
Spacer()
Text(format(bytes: user.size))
.foregroundColor(.secondary)
Button("Очистить") {
clearCache(for: user.id)
}
.buttonStyle(.borderless)
}
}
}
}
}
.navigationTitle("Данные и кэш")
.onAppear(perform: refreshCacheStats)
}
private func refreshCacheStats() {
let userIds = cacheService.getAllCachedUserIds()
self.cachedUsers = userIds.map { id in
let size = cacheService.sizeOfCache(forUserId: id)
return CachedUserInfo(id: id, size: size)
}.sorted { $0.size > $1.size }
self.totalCacheSize = cacheService.sizeOfAllCache()
}
private func clearCache(for userId: String) {
cacheService.clearCache(forUserId: userId)
refreshCacheStats()
}
private func clearAllCache() {
cacheService.clearAllCache()
refreshCacheStats()
}
private func clearOtherUsersCache() {
let otherUsers = cachedUsers.filter { $0.id != currentUserId }
for user in otherUsers {
cacheService.clearCache(forUserId: user.id)
}
refreshCacheStats()
}
private func format(bytes: Int64) -> String {
let formatter = ByteCountFormatter()
formatter.allowedUnits = [.useAll]
formatter.countStyle = .file
return formatter.string(fromByteCount: bytes)
}
}
struct CachedUserInfo: Identifiable {
let id: String
let size: Int64
}

View File

@ -172,136 +172,3 @@ struct SettingsView: View {
} }
} }
struct DataSettingsView: View {
let currentUserId: String
private let cacheService = AvatarCacheService.shared
@State private var cachedUsers: [CachedUserInfo] = []
@State private var totalCacheSize: Int64 = 0
@State private var showClearAllConfirmation = false
@State private var showClearOthersConfirmation = false
@State private var showClearCurrentConfirmation = false
var body: some View {
Form {
Section(header: Text("Общая информация"), footer: Text("Размер кэша аватаров на диске.")) {
HStack {
Text("Общий размер")
Spacer()
Text(format(bytes: totalCacheSize))
.foregroundColor(.secondary)
}
}
Section(header: Text("Массовая отчистка")) {
Button("Очистить кэш текущего пользователя", role: .destructive) {
showClearCurrentConfirmation = true
}
.confirmationDialog(
"Вы уверены, что хотите очистить кэш для текущего пользователя?",
isPresented: $showClearCurrentConfirmation,
titleVisibility: .visible
) {
Button("Очистить", role: .destructive) {
clearCache(for: currentUserId)
}
}
Button("Очистить кэш (кроме текущего)", role: .destructive) {
showClearOthersConfirmation = true
}
.confirmationDialog(
"Вы уверены, что хотите очистить кэш для всех, кроме текущего пользователя?",
isPresented: $showClearOthersConfirmation,
titleVisibility: .visible
) {
Button("Очистить", role: .destructive, action: clearOtherUsersCache)
}
Button("Очистить весь кэш", role: .destructive) {
showClearAllConfirmation = true
}
.confirmationDialog(
"Вы уверены, что хотите очистить весь кэш аватаров? Это действие необратимо.",
isPresented: $showClearAllConfirmation,
titleVisibility: .visible
) {
Button("Очистить всё", role: .destructive, action: clearAllCache)
}
}
Section(header: Text("Кэш по пользователям")) {
if cachedUsers.isEmpty {
Text("Кэш пуст")
.foregroundColor(.secondary)
} else {
ForEach(cachedUsers) { user in
HStack {
VStack(alignment: .leading) {
Text(user.id)
.font(.system(.body, design: .monospaced))
.lineLimit(1)
.truncationMode(.middle)
if user.id == currentUserId {
Text("Текущий")
.font(.caption)
.foregroundColor(.accentColor)
}
}
Spacer()
Text(format(bytes: user.size))
.foregroundColor(.secondary)
Button("Очистить") {
clearCache(for: user.id)
}
.buttonStyle(.borderless)
}
}
}
}
}
.navigationTitle("Данные и кэш")
.onAppear(perform: refreshCacheStats)
}
private func refreshCacheStats() {
let userIds = cacheService.getAllCachedUserIds()
self.cachedUsers = userIds.map { id in
let size = cacheService.sizeOfCache(forUserId: id)
return CachedUserInfo(id: id, size: size)
}.sorted { $0.size > $1.size }
self.totalCacheSize = cacheService.sizeOfAllCache()
}
private func clearCache(for userId: String) {
cacheService.clearCache(forUserId: userId)
refreshCacheStats()
}
private func clearAllCache() {
cacheService.clearAllCache()
refreshCacheStats()
}
private func clearOtherUsersCache() {
let otherUsers = cachedUsers.filter { $0.id != currentUserId }
for user in otherUsers {
cacheService.clearCache(forUserId: user.id)
}
refreshCacheStats()
}
private func format(bytes: Int64) -> String {
let formatter = ByteCountFormatter()
formatter.allowedUnits = [.useAll]
formatter.countStyle = .file
return formatter.string(fromByteCount: bytes)
}
}
struct CachedUserInfo: Identifiable {
let id: String
let size: Int64
}