Initial commit: suixinkan_ios UIKit rewrite project.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 14:33:31 +08:00
commit 9edf993432
297 changed files with 47151 additions and 0 deletions

View File

@ -0,0 +1,138 @@
//
// TaskCloudFileSelectionViewModel.swift
// suixinkan
//
// Created by Codex on 2026/6/23.
//
import Foundation
///
enum TaskCloudFileFilter: Int, CaseIterable, Identifiable {
case all = 0
case video = 1
case image = 2
var id: Int { rawValue }
///
var title: String {
switch self {
case .all:
"全部"
case .video:
"视频"
case .image:
"图片"
}
}
}
/// ViewModel
@MainActor
final class TaskCloudFileSelectionViewModel {
var onChange: (() -> Void)?
var path: [CloudDriveFile] = [CloudDriveFile(id: 0, name: "云盘")] { didSet { onChange?() } }
var files: [CloudDriveFile] = [] { didSet { onChange?() } }
var total = 0 { didSet { onChange?() } }
var page = 1 { didSet { onChange?() } }
var searchText = "" { didSet { onChange?() } }
var selectedFilter: TaskCloudFileFilter = .all { didSet { onChange?() } }
var selectedFiles: [CloudDriveFile] = [] { didSet { onChange?() } }
var isLoading = false { didSet { onChange?() } }
var isLoadingMore = false { didSet { onChange?() } }
var errorMessage: String? { didSet { onChange?() } }
private let pageSize = 20
/// ID
var currentFolderId: Int {
path.last?.id ?? 0
}
///
var hasMore: Bool {
files.count < total
}
///
func reload(api: any TaskServing) async throws {
isLoading = true
errorMessage = nil
defer { isLoading = false }
do {
let payload = try await requestFiles(api: api, page: 1)
page = 1
files = payload.list
total = payload.total
} catch {
files = []
total = 0
page = 1
errorMessage = error.localizedDescription
throw error
}
}
///
func loadMore(api: any TaskServing) async throws {
guard hasMore, !isLoadingMore else { return }
isLoadingMore = true
defer { isLoadingMore = false }
let nextPage = page + 1
let payload = try await requestFiles(api: api, page: nextPage)
page = nextPage
total = payload.total
files.append(contentsOf: payload.list)
}
///
func enterFolder(_ folder: CloudDriveFile, api: any TaskServing) async throws {
guard folder.isFolder else { return }
path.append(folder)
try await reload(api: api)
}
///
func popToFolder(at index: Int, api: any TaskServing) async throws {
guard path.indices.contains(index) else { return }
path = Array(path.prefix(index + 1))
try await reload(api: api)
}
///
func toggleSelection(_ file: CloudDriveFile) {
guard !file.isFolder else { return }
if let index = selectedFiles.firstIndex(where: { $0.id == file.id }) {
selectedFiles.remove(at: index)
} else {
selectedFiles.append(file)
}
}
///
func isSelected(_ file: CloudDriveFile) -> Bool {
selectedFiles.contains { $0.id == file.id }
}
///
func makeSelectionItems() -> [TaskCloudSelectionItem] {
selectedFiles.map {
TaskCloudSelectionItem(id: $0.id, fileName: $0.name, fileType: $0.type, remark: "")
}
}
///
private func requestFiles(api: any TaskServing, page: Int) async throws -> ListPayload<CloudDriveFile> {
try await api.cloudFileList(
parentFolderId: currentFolderId,
name: searchText.trimmingCharacters(in: .whitespacesAndNewlines),
type: selectedFilter.rawValue,
orderBy: 2,
page: page,
pageSize: pageSize
)
}
}