feat: 多模块功能更新 - 文件传输/多语言/NFC/首页组件/进度美化等

- 文件传输: 设备发现、LAN发现服务优化
- NFC分享: provider和service增强
- 多语言: 16种语言翻译补全
- 首页: 句子详情面板、收藏页、离线页优化
- 我的: 成就、个人资料、签到、设置页面更新
- 新增: AR视图、进度美化页、Hive安全访问、鸿蒙兼容助手、共享组件
- iOS Widget: Intents扩展、XianyanWidget更新
- 鸿蒙: 6个卡片页面更新
- 其他: 路由注册、缓存配置、崩溃监控、TTS播放器等
This commit is contained in:
Developer
2026-06-04 04:08:31 +08:00
parent 74b615afc4
commit 67f26ff166
64 changed files with 6122 additions and 408 deletions

View File

@@ -0,0 +1,131 @@
// ============================================================
// Widget AppIntent
// : 2026-06-04
// : 2026-06-04
// : iOS Widget///
// : iOS 17.0+ iOS 14-16 Link
// : Widget Extension 使 UIApplication.shared
// App Group UserDefaults APP
// ============================================================
import WidgetKit
import AppIntents
private let sharedDefaults = UserDefaults(suiteName: "group.apps.xy.xianyan.share")
// MARK: - Widget Intent
/// Widget
struct RefreshWidgetIntent: AppIntent {
static var title: LocalizedStringResource = "刷新"
static var description: IntentDescription = "刷新当前Widget内容"
func perform() async throws -> some IntentResult {
// widgetAPP
sharedDefaults?.set("DailySentence", forKey: "widget_pending_refresh")
sharedDefaults?.synchronize()
// WidgetKittimeline
WidgetCenter.shared.reloadTimelines(ofKind: "DailySentenceWidget")
return .result()
}
}
// MARK: - Intent
///
struct LikeSentenceIntent: AppIntent {
static var title: LocalizedStringResource = "点赞"
static var description: IntentDescription = "喜欢这句句子"
func perform() async throws -> some IntentResult {
// UserDefaultsAPP
sharedDefaults?.set(true, forKey: "widget_action_like")
sharedDefaults?.set(Date(), forKey: "widget_action_like_time")
sharedDefaults?.synchronize()
return .result()
}
}
// MARK: - Intent
///
struct ShareContentIntent: AppIntent {
static var title: LocalizedStringResource = "分享"
static var description: IntentDescription = "分享当前内容"
func perform() async throws -> some IntentResult {
// APP
sharedDefaults?.set("sentence", forKey: "widget_action_share_type")
sharedDefaults?.set(Date(), forKey: "widget_action_share_time")
sharedDefaults?.synchronize()
return .result()
}
}
// MARK: - Intent
///
struct NextContentIntent: AppIntent {
static var title: LocalizedStringResource = "下一句"
static var description: IntentDescription = "切换显示下一条内容"
func perform() async throws -> some IntentResult {
//
sharedDefaults?.set("DailySentence", forKey: "widget_action_next_widget")
sharedDefaults?.set(Date(), forKey: "widget_action_next_time")
sharedDefaults?.synchronize()
// widget
WidgetCenter.shared.reloadTimelines(ofKind: "DailySentenceWidget")
return .result()
}
}
// MARK: - Intent
///
struct CheckinIntent: AppIntent {
static var title: LocalizedStringResource = "签到"
static var description: IntentDescription = "执行今日签到"
func perform() async throws -> some IntentResult {
// APP
sharedDefaults?.set(true, forKey: "widget_action_checkin")
sharedDefaults?.set(Date(), forKey: "widget_action_checkin_time")
sharedDefaults?.synchronize()
// widget
WidgetCenter.shared.reloadTimelines(ofKind: "CheckinWidget")
return .result()
}
}
// MARK: - APP Intent
/// APP
struct OpenAppPageIntent: AppIntent {
static var title: LocalizedStringResource = "打开APP"
static var description: IntentDescription = "打开闲言APP"
func perform() async throws -> some IntentResult {
// APP
sharedDefaults?.set("/home", forKey: "widget_open_page")
sharedDefaults?.set(Date(), forKey: "widget_open_page_time")
sharedDefaults?.synchronize()
return .result()
}
}
// MARK: - Intent
///
struct SaveCardIntent: AppIntent {
static var title: LocalizedStringResource = "保存"
static var description: IntentDescription = "保存日签卡片到相册"
func perform() async throws -> some IntentResult {
// APP
sharedDefaults?.set(true, forKey: "widget_action_save_card")
sharedDefaults?.set(Date(), forKey: "widget_action_save_card_time")
sharedDefaults?.synchronize()
return .result()
}
}

View File

@@ -1,5 +1,6 @@
import WidgetKit
import SwiftUI
import AppIntents
struct DailySentenceEntry: TimelineEntry {
let date: Date
@@ -322,11 +323,59 @@ struct DailySentenceWidgetEntryView: View {
var body: some View {
let colors = WidgetColors(isDark: entry.isDark)
VStack(alignment: .leading, spacing: 8) {
Text(entry.sentence)
.font(.body)
.foregroundColor(colors.primary)
.lineLimit(3)
.multilineTextAlignment(.leading)
HStack {
Text(entry.sentence)
.font(.body)
.foregroundColor(colors.primary)
.lineLimit(3)
.multilineTextAlignment(.leading)
Spacer()
// iOS 17+
if #available(iOS 17.0, *) {
HStack(spacing: 6) {
//
Button(intent: LikeSentenceIntent()) {
Image(systemName: "heart")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: ShareContentIntent()) {
Image(systemName: "square.and.arrow.up")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: RefreshWidgetIntent()) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
}
} else {
// iOS 14-16
Link(destination: URL(string: "xianyanwidget://refresh?widget=DailySentence")!) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
}
}
Spacer()
Text("\(entry.author)")
.font(.caption)
@@ -348,6 +397,40 @@ struct ReadlaterWidgetEntryView: View {
.font(.headline)
.foregroundColor(colors.primary)
Spacer()
// iOS 17+
if #available(iOS 17.0, *) {
HStack(spacing: 6) {
//
Button(intent: OpenAppPageIntent()) {
Image(systemName: "book.fill")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: RefreshWidgetIntent()) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
}
} else {
Link(destination: URL(string: "xianyanwidget://refresh?widget=Readlater")!) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
}
}
if !entry.previewText.isEmpty {
Text(entry.previewText)
@@ -366,6 +449,53 @@ struct DailyCardWidgetEntryView: View {
var body: some View {
let colors = WidgetColors(isDark: entry.isDark)
VStack(spacing: 8) {
HStack {
Spacer()
// iOS 17+
if #available(iOS 17.0, *) {
HStack(spacing: 6) {
//
Button(intent: SaveCardIntent()) {
Image(systemName: "square.and.arrow.down")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: ShareContentIntent()) {
Image(systemName: "square.and.arrow.up")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: RefreshWidgetIntent()) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
}
} else {
Link(destination: URL(string: "xianyanwidget://refresh?widget=DailyCard")!) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
}
}
Spacer()
Text(entry.sentence)
.font(.body)
@@ -387,8 +517,55 @@ struct FortuneWidgetEntryView: View {
var body: some View {
let colors = WidgetColors(isDark: entry.isDark)
VStack(alignment: .leading, spacing: 6) {
Text(entry.keyword)
.font(.title2)
HStack {
Text(entry.keyword)
.font(.title2)
Spacer()
// iOS 17+
if #available(iOS 17.0, *) {
HStack(spacing: 6) {
//
Button(intent: NextContentIntent()) {
Image(systemName: "shuffle")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: ShareContentIntent()) {
Image(systemName: "square.and.arrow.up")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
//
Button(intent: RefreshWidgetIntent()) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
}
} else {
Link(destination: URL(string: "xianyanwidget://refresh?widget=Fortune")!) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
}
}
Text(entry.text)
.font(.caption)
.foregroundColor(colors.primary)
@@ -443,10 +620,21 @@ struct SolarTermWidgetEntryView: View {
var body: some View {
let colors = WidgetColors(isDark: entry.isDark)
VStack(alignment: .leading, spacing: 6) {
Text(entry.name)
.font(.title3)
.fontWeight(.bold)
.foregroundColor(colors.primary)
HStack {
Text(entry.name)
.font(.title3)
.fontWeight(.bold)
.foregroundColor(colors.primary)
Spacer()
Link(destination: URL(string: "xianyanwidget://refresh?widget=SolarTerm")!) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
}
Text(entry.poem)
.font(.caption)
.foregroundColor(colors.secondary)
@@ -462,10 +650,45 @@ struct CheckinWidgetEntryView: View {
var body: some View {
let colors = WidgetColors(isDark: entry.isDark)
VStack(spacing: 4) {
Text("连续\(entry.days)")
.font(.title3)
.fontWeight(.bold)
.foregroundColor(colors.primary)
HStack {
Text("连续\(entry.days)")
.font(.title3)
.fontWeight(.bold)
.foregroundColor(colors.primary)
Spacer()
// iOS 17+
if #available(iOS 17.0, *) {
//
Button(intent: CheckinIntent()) {
Text(entry.todayDone ? "" : "📝")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(6)
.background(colors.bg.opacity(0.5))
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.buttonStyle(.plain)
//
Button(intent: RefreshWidgetIntent()) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
.buttonStyle(.plain)
} else {
Link(destination: URL(string: "xianyanwidget://refresh?widget=Checkin")!) {
Image(systemName: "arrow.clockwise")
.font(.caption2)
.foregroundColor(colors.secondary)
.padding(4)
.background(colors.bg.opacity(0.5))
.clipShape(Circle())
}
}
}
Text(entry.todayDone ? "✅ 今日已签" : "📝 点击签到")
.font(.caption)
.foregroundColor(colors.secondary)