diff --git a/App/MapHomeView.swift b/App/MapHomeView.swift index b39a5cd..befbd43 100644 --- a/App/MapHomeView.swift +++ b/App/MapHomeView.swift @@ -431,8 +431,8 @@ struct MapHomeView: View { HStack { VStack(alignment: .leading, spacing: 3) { Text(mapState.displayName ?? "当前选点").font(.subheadline.weight(.semibold)).lineLimit(1) - coordinateRow(label: "国内标准 GCJ-02", system: .gcj02) - coordinateRow(label: "国际标准 WGS-84", system: .wgs84) + coordinateRow(label: "GCJ-02(国内)", system: .gcj02) + coordinateRow(label: "WGS-84(国际)", system: .wgs84) } Spacer() // 帮助说明按钮 @@ -768,11 +768,15 @@ struct MapHomeView: View { Text(label) .font(.caption2.weight(.medium)) .foregroundStyle(.secondary) - .frame(width: 112, alignment: .leading) + .lineLimit(1) + .fixedSize(horizontal: true, vertical: false) Text(text) .font(.caption.monospaced()) .foregroundStyle(copiedCoordinateSystem == system ? .green : .secondary) .lineLimit(1) + .minimumScaleFactor(0.72) + .allowsTightening(true) + .layoutPriority(1) } .contentShape(Rectangle()) .onTapGesture { @@ -1296,7 +1300,7 @@ struct MapHomeView: View { mapState.focusSelection(distanceMeters: currentViewport) // Persist both forms once from the explicitly typed input boundary. LastCoordinateStore.save(coordinatePair: pair, zoomMeters: currentViewport) - favorites.select(nil) + favorites.selectMatching(coordinatePair: pair) scheduleGeocode(pair: pair, revision: mapState.selection.revision) } diff --git a/Shared/FavoriteLocationStore.swift b/Shared/FavoriteLocationStore.swift index 008bad5..0f4cd7e 100644 --- a/Shared/FavoriteLocationStore.swift +++ b/Shared/FavoriteLocationStore.swift @@ -160,6 +160,18 @@ final class FavoriteLocationStore: ObservableObject { defaults.set(id?.uuidString, forKey: Keys.selectedID) } + @discardableResult + func selectMatching(coordinatePair: CoordinatePair) -> FavoriteLocation? { + let matchingFavorite = favorites.first { + $0.coordinatePair.matchesWGS84( + latitude: coordinatePair.wgs84.latitude, + longitude: coordinatePair.wgs84.longitude + ) + } + select(matchingFavorite?.id) + return matchingFavorite + } + func rename(_ id: UUID, to name: String) { guard let idx = favorites.firstIndex(where: { $0.id == id }) else { return } favorites[idx].name = name diff --git a/Tests/PaopaoLocationSpooferTests/FavoriteLocationStoreTests.swift b/Tests/PaopaoLocationSpooferTests/FavoriteLocationStoreTests.swift index e1186db..b9fa16f 100644 --- a/Tests/PaopaoLocationSpooferTests/FavoriteLocationStoreTests.swift +++ b/Tests/PaopaoLocationSpooferTests/FavoriteLocationStoreTests.swift @@ -19,6 +19,39 @@ final class FavoriteLocationStoreTests: XCTestCase { XCTAssertEqual(FavoriteLocationStore(defaults: defaults).selectedFavorite?.name, "深圳湾") } + func testSelectingMatchingCoordinatePairRestoresFavoriteSelection() { + let suite = "FavoriteLocationStoreTests.\(UUID().uuidString)" + let defaults = UserDefaults(suiteName: suite)! + defer { defaults.removePersistentDomain(forName: suite) } + let store = FavoriteLocationStore(defaults: defaults) + let favorite = store.save( + name: "深圳湾", + coordinatePair: CoordinateConverter.coordinatePair( + lat: 22.491_438, + lon: 113.945_702, + mapCoordinateSystem: .wgs84 + ), + accuracy: 20 + ) + store.select(nil) + + let nearbyRealtimePair = CoordinateConverter.coordinatePair( + lat: 22.491_488, + lon: 113.945_752, + mapCoordinateSystem: .wgs84 + ) + XCTAssertEqual(store.selectMatching(coordinatePair: nearbyRealtimePair)?.id, favorite.id) + XCTAssertEqual(store.selectedFavoriteID, favorite.id) + + let unrelatedPair = CoordinateConverter.coordinatePair( + lat: 31.2304, + lon: 121.4737, + mapCoordinateSystem: .wgs84 + ) + XCTAssertNil(store.selectMatching(coordinatePair: unrelatedPair)) + XCTAssertNil(store.selectedFavoriteID) + } + func testFavoriteStoresBothFormsAndSelectsMatchingPairWithoutReadConversion() { let suite = "FavoriteLocationStoreTests.\(UUID().uuidString)" let defaults = UserDefaults(suiteName: suite)! diff --git a/Tests/map_refactor_contract_test.sh b/Tests/map_refactor_contract_test.sh index 740973c..4ccdff5 100755 --- a/Tests/map_refactor_contract_test.sh +++ b/Tests/map_refactor_contract_test.sh @@ -69,6 +69,7 @@ grep -q 'refreshRuntimeMapCoordinateSystem(reason:' "$CONVERTER" || fail "fixed- grep -q 'scheduleBluePointMapCoordinateSystemRefresh()' "$MAP_HOME" || fail "native blue-point samples must trigger runtime map-type refresh while spoofing" ! grep -A3 'private func scheduleBluePointMapCoordinateSystemRefresh' "$MAP_HOME" | grep -q 'spoofState == .active' || fail "blue-point map-type refresh must also detect the return to physical location" grep -q 'awaitCoordinatedMapCoordinateSystemRefresh(reason: "点击实时定位")' "$MAP_HOME" || fail "realtime button must await the coordinated map-type refresh" +grep -q 'favorites.selectMatching(coordinatePair: pair)' "$MAP_HOME" || fail "realtime selection must restore a matching favorite selection" grep -q 'awaitCoordinatedMapCoordinateSystemRefresh(reason: "保存收藏")' "$MAP_HOME" || fail "favorite save must await the coordinated map-type refresh" grep -q 'awaitCoordinatedMapCoordinateSystemRefresh(reason: "App回到前台")' "$MAP_HOME" || fail "foreground recovery must reuse the coordinated map-type refresh" grep -q '地图坐标标准运行期检测结果已过期,取消写入' "$CONVERTER" || fail "cancelled runtime probes must not mutate the global map type" @@ -76,8 +77,10 @@ grep -q '地图坐标标准运行期检测结果已过期,取消写入' "$CONV grep -q 'clearRealtimeLocationForMapCoordinateSystemChange' "$MAP_HOME" || fail "map-type changes must discard superseded blue-point samples" grep -q '地图坐标类型已变化' "$MAP_HOME" || fail "map-type changes must emit an explicit searchable business log" grep -q '图钉已按新类型重设' "$MAP_HOME" || fail "map-type change log must report pin reprojection" -grep -q '国内标准 GCJ-02' "$MAP_HOME" || fail "current selection panel must show GCJ-02" -grep -q '国际标准 WGS-84' "$MAP_HOME" || fail "current selection panel must show WGS-84" +grep -q 'coordinateRow(label: "GCJ-02(国内)", system: .gcj02)' "$MAP_HOME" || fail "current selection panel must label the domestic coordinate as GCJ-02" +grep -q 'coordinateRow(label: "WGS-84(国际)", system: .wgs84)' "$MAP_HOME" || fail "current selection panel must label the international coordinate as WGS-84" +grep -q 'fixedSize(horizontal: true, vertical: false)' "$MAP_HOME" || fail "coordinate labels must keep their natural single-line width" +grep -q 'minimumScaleFactor(0.72)' "$MAP_HOME" || fail "coordinate values must shrink to remain on one line" grep -q 'phase = .map' "$CONTENT" || fail "ContentView must explicitly gate MapHomeView construction" ! grep -q 'startTileProbe' "$MAP_HOME" || fail "MapHomeView must not start a second fixed-anchor coordinate-system probe" ! grep -q 'initializeMap()' "$MAP_HOME" || fail "MapHomeView must not replay a second map initialization from onAppear"