选择图片分享功能

This commit is contained in:
2025-08-17 22:08:25 +08:00
parent e6afca5ba6
commit d80289fe73
19 changed files with 1402 additions and 110 deletions

View File

@@ -0,0 +1,291 @@
import SwiftUI
import Foundation
// UserDefaults
extension UserDefaults {
// [album_id: 访]
private var historyRecordsKey: String { "history_records" }
var historyRecords: [String: TimeInterval] {
get {
(object(forKey: historyRecordsKey) as? [String: TimeInterval]) ?? [:]
}
set {
set(newValue, forKey: historyRecordsKey)
}
}
//
func addHistory(albumId: String) {
var records = historyRecords
records[albumId] = Date().timeIntervalSince1970 //
historyRecords = records
}
//
func removeHistory(albumId: String) {
var records = historyRecords
records.removeValue(forKey: albumId)
historyRecords = records
}
//
func clearAllHistory() {
historyRecords = [:]
}
}
struct ProfileView: View {
//
let username = "Jetson User"
//
@State private var favoriteAlbums: [AlbumItem] = []
@State private var isLoadingFavorites = false
//
@State private var historyAlbums: [AlbumItem] = []
@State private var isLoadingHistory = false
@State private var showHistoryEmpty = false
//
@State private var showError = false
@State private var errorMessage = ""
var body: some View {
NavigationStack {
List {
//
Section {
HStack(alignment: .center, spacing: 12) {
//
Image(systemName: "person.circle.fill")
.resizable()
.frame(width: 80, height: 80)
.foregroundColor(.blue)
//
VStack(spacing: 4) {
Text(username)
.font(.headline)
}
}
.padding(.vertical, 20)
}
//
Section(header: Text("我的收藏")
.font(.headline)) {
if isLoadingFavorites {
HStack {
Spacer()
ProgressView("加载收藏中...")
Spacer()
}
.padding(.vertical, 20)
} else if favoriteAlbums.isEmpty {
Text("暂无收藏,快去收藏喜欢的漫画吧~")
.foregroundColor(.gray)
.padding(.vertical, 20)
} else {
ForEach(favoriteAlbums) { item in
NavigationLink(destination: PhotoView(albumId: item.album_id)) {
VStack(alignment: .leading, spacing: 4) {
Text(item.title)
.font(.subheadline)
.lineLimit(2)
Text("ID: \(item.album_id)")
.font(.caption)
.foregroundColor(.gray)
}
}
}
.onDelete(perform: removeFromFavorites)
}
}
//
Section(header: HStack {
Text("浏览历史")
.font(.headline)
Spacer()
Button("清除全部") {
clearAllHistory()
}
.foregroundColor(.red)
.font(.subheadline)
}) {
if isLoadingHistory {
HStack {
Spacer()
ProgressView("加载历史中...")
Spacer()
}
.padding(.vertical, 20)
} else if historyAlbums.isEmpty {
Text("暂无浏览记录")
.foregroundColor(.gray)
.padding(.vertical, 20)
} else {
ForEach(historyAlbums) { item in
NavigationLink(destination: PhotoView(albumId: item.album_id)) {
VStack(alignment: .leading, spacing: 4) {
Text(item.title)
.font(.subheadline)
.lineLimit(2)
Text("ID: \(item.album_id)")
.font(.caption)
.foregroundColor(.gray)
}
}
}
.onDelete(perform: removeFromHistory)
}
}
//
Section(header: Text("设置")) {
Button(action: {}) {
HStack {
Image(systemName: "gear")
.foregroundColor(.gray)
Text("设置")
}
}
}
}
.navigationTitle("我的")
.toolbar {
EditButton()
}
.alert(isPresented: $showError) {
Alert(title: Text("加载失败"), message: Text(errorMessage), dismissButton: .default(Text("确定")))
}
.onAppear {
loadFavoriteAlbums()
loadHistoryAlbums() //
}
}
}
// MARK: -
private func loadFavoriteAlbums() {
let favoriteIds = UserDefaults.standard.favoriteAlbumIds
guard !favoriteIds.isEmpty else {
favoriteAlbums = []
return
}
isLoadingFavorites = true
favoriteAlbums = []
let group = DispatchGroup()
for id in favoriteIds {
group.enter()
fetchAlbumInfo(albumId: id) { albumItem in
if let item = albumItem {
favoriteAlbums.append(item)
}
group.leave()
}
}
group.notify(queue: .main) {
favoriteAlbums.sort { $0.album_id > $1.album_id }
isLoadingFavorites = false
}
}
private func removeFromFavorites(at offsets: IndexSet) {
guard let index = offsets.first else { return }
let removedItem = favoriteAlbums[index]
favoriteAlbums.remove(at: index)
var favorites = UserDefaults.standard.favoriteAlbumIds
favorites.removeAll { $0 == removedItem.album_id }
UserDefaults.standard.favoriteAlbumIds = favorites
}
// MARK: -
private func loadHistoryAlbums() {
let historyRecords = UserDefaults.standard.historyRecords
//
let sortedIds = historyRecords.keys.sorted {
historyRecords[$0] ?? 0 > historyRecords[$1] ?? 0
}
guard !sortedIds.isEmpty else {
historyAlbums = []
return
}
isLoadingHistory = true
historyAlbums = []
let group = DispatchGroup()
for id in sortedIds {
group.enter()
fetchAlbumInfo(albumId: id) { albumItem in
if let item = albumItem {
historyAlbums.append(item)
}
group.leave()
}
}
group.notify(queue: .main) {
isLoadingHistory = false
}
}
private func removeFromHistory(at offsets: IndexSet) {
guard let index = offsets.first else { return }
let removedItem = historyAlbums[index]
historyAlbums.remove(at: index)
UserDefaults.standard.removeHistory(albumId: removedItem.album_id)
}
private func clearAllHistory() {
UserDefaults.standard.clearAllHistory()
historyAlbums = []
}
// MARK: -
private func fetchAlbumInfo(albumId: String, completion: @escaping (AlbumItem?) -> Void) {
let urlString = "http://jm.rbq.college/album/\(albumId)/"
guard let url = URL(string: urlString) else {
completion(nil)
return
}
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
DispatchQueue.main.async {
showError(message: "加载失败: \(error.localizedDescription)")
}
completion(nil)
return
}
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200,
let data = data else {
completion(nil)
return
}
do {
let album = try JSONDecoder().decode(Album.self, from: data)
let albumItem = AlbumItem(album_id: album.album_id, title: album.name)
completion(albumItem)
} catch {
print("解析数据失败: \(error)")
completion(nil)
}
}.resume()
}
private func showError(message: String) {
errorMessage = message
showError = true
}
}