Skip to content

Commit 8c26bc2

Browse files
committed
优化图览页面
1 parent 0f4b28b commit 8c26bc2

2 files changed

Lines changed: 139 additions & 6 deletions

File tree

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//
2+
// AlbumTopicRowView.swift
3+
// Smth
4+
//
5+
// 图览话题行视图组件,展示图片和标题,图片占据大部分空间
6+
// Created by tony
7+
//
8+
9+
import SwiftUI
10+
11+
struct AlbumTopicRowView: View {
12+
@Environment(\.colorScheme) private var colorScheme
13+
14+
let topic: Topic
15+
let isVisited: Bool
16+
17+
init(topic: Topic, isVisited: Bool = false) {
18+
self.topic = topic
19+
self.isVisited = isVisited
20+
}
21+
22+
private var firstImageAttachment: Attachment? {
23+
guard let attachments = topic.article?.attachments,
24+
!attachments.isEmpty else {
25+
return nil
26+
}
27+
// 查找第一个图片类型的附件
28+
return attachments.first { attachment in
29+
let type = attachment.type.lowercased()
30+
return type.contains("image") ||
31+
type.contains("jpg") ||
32+
type.contains("jpeg") ||
33+
type.contains("png") ||
34+
type.contains("gif") ||
35+
type.contains("webp")
36+
} ?? attachments.first
37+
}
38+
39+
var body: some View {
40+
VStack(alignment: .leading, spacing: 0) {
41+
// 图片部分 - 占据大部分空间
42+
if let attachment = firstImageAttachment,
43+
let ks3Url = attachment.ks3Url,
44+
let imageUrl = URL(string: ks3Url) {
45+
CachedAsyncImage(url: imageUrl) { image in
46+
image
47+
.resizable()
48+
.aspectRatio(contentMode: .fill)
49+
} placeholder: {
50+
Rectangle()
51+
.fill(Color.gray.opacity(0.2))
52+
.overlay(
53+
ProgressView()
54+
.tint(AppTheme.accentColor(for: colorScheme))
55+
)
56+
}
57+
.frame(height: 280)
58+
.clipped()
59+
} else {
60+
// 如果没有图片,显示占位符
61+
Rectangle()
62+
.fill(Color.gray.opacity(0.2))
63+
.frame(height: 280)
64+
.overlay(
65+
VStack(spacing: 12) {
66+
Image(systemName: "photo")
67+
.font(.system(size: 48))
68+
.foregroundColor(.gray)
69+
Text("暂无图片")
70+
.font(.subheadline)
71+
.foregroundColor(.secondary)
72+
}
73+
)
74+
}
75+
76+
// 标题部分 - 在底部
77+
VStack(alignment: .leading, spacing: 8) {
78+
Text(topic.subject)
79+
.font(.system(.headline, design: .rounded).weight(.semibold))
80+
.foregroundColor(.primary)
81+
.lineLimit(2)
82+
.multilineTextAlignment(.leading)
83+
}
84+
.padding(.horizontal, AppTheme.compactSpacing)
85+
.padding(.vertical, 12)
86+
.frame(maxWidth: .infinity, alignment: .leading)
87+
.background(
88+
Rectangle()
89+
.fill(AppTheme.surfaceBackground(for: colorScheme))
90+
)
91+
}
92+
.frame(maxWidth: .infinity, alignment: .leading)
93+
.background(
94+
RoundedRectangle(cornerRadius: AppTheme.cardCornerRadius, style: .continuous)
95+
.fill(isVisited ? AppTheme.subduedSurface(for: colorScheme) : AppTheme.surfaceBackground(for: colorScheme))
96+
)
97+
.overlay(
98+
RoundedRectangle(cornerRadius: AppTheme.cardCornerRadius, style: .continuous)
99+
.stroke(
100+
AppTheme.borderColor(for: colorScheme).opacity(isVisited ? 0.4 : 1.0),
101+
lineWidth: 1
102+
)
103+
)
104+
.clipShape(RoundedRectangle(cornerRadius: AppTheme.cardCornerRadius, style: .continuous))
105+
.shadow(
106+
color: AppTheme.shadowColor(for: colorScheme).opacity(isVisited ? 0.08 : 0.16),
107+
radius: isVisited ? 10 : 14,
108+
y: isVisited ? 3 : 8
109+
)
110+
.contentShape(RoundedRectangle(cornerRadius: AppTheme.cardCornerRadius, style: .continuous))
111+
.accessibilityElement(children: .combine)
112+
.accessibilityLabel("\(topic.subject)")
113+
}
114+
}
115+

App/Modules/Home/HomeView.swift

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,41 @@ struct HomeView: View {
1818
@State private var selectedIndex: Int = 0
1919
@State private var showProfileView = false
2020
@State private var hasInitializedFirstNavigation = false
21+
22+
private var currentNavigationType: String? {
23+
guard navigationViewModel.navigations.indices.contains(selectedIndex) else {
24+
return nil
25+
}
26+
return navigationViewModel.navigations[selectedIndex].type
27+
}
28+
29+
private var isAlbumView: Bool {
30+
currentNavigationType == "album"
31+
}
2132

2233
var body: some View {
2334
ScrollView {
2435
LazyVStack(spacing: AppTheme.compactSpacing, pinnedViews: [.sectionHeaders]) {
2536
Section {
2637
ForEach(viewModel.topics) { topic in
2738
NavigationLink(value: topic) {
28-
TopicRowView(
29-
topic: topic,
30-
isVisited: browsingHistory.visitedTopicIDs.contains(topic.id)
31-
)
32-
.onAppear {
33-
viewModel.loadNextPageIfNeeded(currentItem: topic)
39+
if isAlbumView {
40+
AlbumTopicRowView(
41+
topic: topic,
42+
isVisited: browsingHistory.visitedTopicIDs.contains(topic.id)
43+
)
44+
} else {
45+
TopicRowView(
46+
topic: topic,
47+
isVisited: browsingHistory.visitedTopicIDs.contains(topic.id)
48+
)
3449
}
3550
}
3651
.buttonStyle(.plain)
3752
.frame(maxWidth: .infinity, alignment: .leading)
53+
.onAppear {
54+
viewModel.loadNextPageIfNeeded(currentItem: topic)
55+
}
3856
}
3957
} header: {
4058
NavigationSelector(

0 commit comments

Comments
 (0)