Files
OpenStats/Packages/OpenStatsKit/Sources/OpenStatsUI/Design/FlagImage.swift
T
gentpan 8875b6e709 每项独立菜单栏与详情弹窗、网络详情与 DNS、侧边栏主窗口与统一外观
- 菜单栏可每项独立(点击弹出该项窄详情)或合并为一个(点击打开主窗口),详情区块可在设置中勾选
- 网络详情:镜像流量历史、ICMP 连接探测格子、接口与 Wi-Fi、本地与公网 IPv4 / IPv6、SVG 国旗归属地与 ASN、各进程流量
- DNS:刷新缓存,一键切换自动 / Cloudflare / Google / 腾讯 / 阿里云或手动填写;辅助工具协议升至 3,服务名与地址二次校验
- 主窗口:侧边栏切换仪表盘、各指标详情与工具页,宽高可调,卡片按比例伸缩
- 统一外观:白底蓝 / 黑底蓝,窗口、设置与弹窗共用底色,去掉玻璃效果
- 新增网络解析、DNS 校验与国旗代码校验的单元测试;更新 README、架构文档与隐私说明
2026-09-13 05:39:10 +05:00

43 lines
1.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import AppKit
import SwiftUI
/// 国旗:使用包内的 SVG(flag-icons,MIT),不使用 emoji
struct FlagImage: View {
let countryCode: String
var height: CGFloat = DS.Space.s3
var body: some View {
if let image = FlagCache.shared.image(for: countryCode) {
Image(nsImage: image)
.resizable()
.aspectRatio(4 / 3, contentMode: .fit)
.frame(height: height)
.clipShape(RoundedRectangle(cornerRadius: DS.Radius.sm / 2))
.overlay(RoundedRectangle(cornerRadius: DS.Radius.sm / 2).strokeBorder(DS.Palette.border, lineWidth: DS.Size.stroke))
.accessibilityHidden(true)
}
}
}
@MainActor
final class FlagCache {
static let shared = FlagCache()
private var images: [String: NSImage] = [:]
private var missing: Set<String> = []
func image(for countryCode: String) -> NSImage? {
let code = countryCode.lowercased()
// 只接受两位字母,避免拼出包外路径
guard code.count == 2, code.unicodeScalars.allSatisfy({ ("a"..."z").contains($0) }) else { return nil }
if let image = images[code] { return image }
guard !missing.contains(code) else { return nil }
guard let url = Bundle.module.url(forResource: code, withExtension: "svg", subdirectory: "Flags"),
let image = NSImage(contentsOf: url) else {
missing.insert(code)
return nil
}
images[code] = image
return image
}
}