Refactor home to single collection view and add all-functions customization.

Replace scroll/stack layout with one UICollectionView, fix grid column math and Diffable item IDs so location report and quick actions render, and add the customizable all-functions page with persistence and tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 09:57:41 +08:00
parent d8329d19fd
commit 715393e78c
14 changed files with 1222 additions and 209 deletions

View File

@ -0,0 +1,123 @@
//
// AllFunctionsViewModelTests.swift
// suixinkanTests
//
import XCTest
@testable import suixinkan
/// ViewModel
final class AllFunctionsViewModelTests: XCTestCase {
private var defaults: UserDefaults!
private var appStore: AppStore!
private var menuStore: HomeCommonMenuStore!
override func setUp() {
defaults = UserDefaults(suiteName: "AllFunctionsViewModelTests")!
defaults.removePersistentDomain(forName: "AllFunctionsViewModelTests")
appStore = AppStore(defaults: defaults)
menuStore = HomeCommonMenuStore(defaults: defaults)
appStore.userId = "1001"
appStore.accountType = "scenic_user"
appStore.roleCode = AppRoleCode.photographer.rawValue
}
override func tearDown() {
defaults.removePersistentDomain(forName: "AllFunctionsViewModelTests")
super.tearDown()
}
func testLoadFunctionsUsesDefaultFirstFourWhenNoSavedURIs() {
appStore.savePermissionItems([
HomePermissionItem(id: "1", name: "钱包", uri: "wallet"),
HomePermissionItem(id: "2", name: "云盘", uri: "cloud_management"),
HomePermissionItem(id: "3", name: "任务", uri: "task_management"),
HomePermissionItem(id: "4", name: "设置", uri: "system_settings"),
HomePermissionItem(id: "5", name: "消息", uri: "message_center"),
])
let viewModel = AllFunctionsViewModel(appStore: appStore, commonMenuStore: menuStore)
viewModel.loadFunctions()
XCTAssertEqual(viewModel.commonMenus.map(\.uri), [
"wallet", "cloud_management", "task_management", "system_settings",
])
XCTAssertEqual(viewModel.moreMenus.map(\.uri), ["message_center"])
XCTAssertEqual(
menuStore.savedCommonURIs(
accountScope: appStore.accountCachePrefix,
roleCode: appStore.roleCode
),
["wallet", "cloud_management", "task_management", "system_settings"]
)
}
func testLoadFunctionsUsesSavedURIsOverDefault() {
appStore.savePermissionItems([
HomePermissionItem(id: "1", name: "钱包", uri: "wallet"),
HomePermissionItem(id: "2", name: "云盘", uri: "cloud_management"),
HomePermissionItem(id: "3", name: "任务", uri: "task_management"),
])
menuStore.saveCommonURIs(
["cloud_management"],
accountScope: appStore.accountCachePrefix,
roleCode: appStore.roleCode
)
let viewModel = AllFunctionsViewModel(appStore: appStore, commonMenuStore: menuStore)
viewModel.loadFunctions()
XCTAssertEqual(viewModel.commonMenus.map(\.uri), ["cloud_management"])
XCTAssertEqual(Set(viewModel.moreMenus.map(\.uri)), Set(["wallet", "task_management"]))
}
func testAddToCommonMovesMenuAndPersists() {
appStore.savePermissionItems([
HomePermissionItem(id: "1", name: "钱包", uri: "wallet"),
HomePermissionItem(id: "2", name: "云盘", uri: "cloud_management"),
])
menuStore.saveCommonURIs(
["wallet"],
accountScope: appStore.accountCachePrefix,
roleCode: appStore.roleCode
)
let viewModel = AllFunctionsViewModel(appStore: appStore, commonMenuStore: menuStore)
viewModel.loadFunctions()
let cloudMenu = viewModel.moreMenus.first { $0.uri == "cloud_management" }!
viewModel.addToCommon(cloudMenu)
XCTAssertEqual(viewModel.commonMenus.map(\.uri), ["wallet", "cloud_management"])
XCTAssertTrue(viewModel.moreMenus.isEmpty)
XCTAssertTrue(viewModel.didCustomize)
XCTAssertEqual(
menuStore.savedCommonURIs(
accountScope: appStore.accountCachePrefix,
roleCode: appStore.roleCode
),
["wallet", "cloud_management"]
)
}
func testRemoveFromCommonMovesMenuAndPersists() {
appStore.savePermissionItems([
HomePermissionItem(id: "1", name: "钱包", uri: "wallet"),
HomePermissionItem(id: "2", name: "云盘", uri: "cloud_management"),
])
menuStore.saveCommonURIs(
["wallet", "cloud_management"],
accountScope: appStore.accountCachePrefix,
roleCode: appStore.roleCode
)
let viewModel = AllFunctionsViewModel(appStore: appStore, commonMenuStore: menuStore)
viewModel.loadFunctions()
let walletMenu = viewModel.commonMenus.first { $0.uri == "wallet" }!
viewModel.removeFromCommon(walletMenu)
XCTAssertEqual(viewModel.commonMenus.map(\.uri), ["cloud_management"])
XCTAssertEqual(viewModel.moreMenus.map(\.uri), ["wallet"])
XCTAssertTrue(viewModel.didCustomize)
}
}