Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions app/src/main/java/cn/gdeiassistant/ui/components/AppChrome.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
Expand Down Expand Up @@ -125,7 +126,7 @@ fun BadgePill(
text = text,
style = MaterialTheme.typography.labelMedium.copy(
fontWeight = FontWeight.Bold,
letterSpacing = 0.5.sp
letterSpacing = 0.sp
),
color = if (onGradient) Color.White else tint
)
Expand Down Expand Up @@ -177,15 +178,17 @@ fun ActionTile(
text = title,
style = MaterialTheme.typography.titleMedium.copy(
fontWeight = FontWeight.Bold
)
),
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
subtitle?.takeIf { it.isNotBlank() }?.let { sub ->
Spacer(modifier = Modifier.size(4.dp))
Text(
text = sub,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
Expand Down Expand Up @@ -259,13 +262,19 @@ fun MetricChip(
Text(
text = label,
style = MaterialTheme.typography.labelSmall,
color = if (onGradient) Color.White.copy(alpha = 0.8f) else MaterialTheme.colorScheme.onSurfaceVariant
color = if (onGradient) Color.White.copy(alpha = 0.8f) else MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.size(4.dp))
Text(
text = value,
style = MaterialTheme.typography.labelLarge.copy(fontSize = 16.sp), // Monospace from labelLarge
color = if (onGradient) Color.White else MaterialTheme.colorScheme.onSurface
color = if (onGradient) Color.White else MaterialTheme.colorScheme.onSurface,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
Expand All @@ -45,9 +47,9 @@ fun BentoCard(
val borderColor = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.42f)
val cardModifier = modifier
.shadow(
elevation = if (onClick != null) 3.dp else 0.dp,
elevation = if (onClick != null) 1.dp else 0.dp,
shape = AppShapes.card,
spotColor = Color.Black.copy(alpha = 0.08f),
spotColor = Color.Black.copy(alpha = 0.05f),
ambientColor = Color.Black.copy(alpha = 0.03f)
)
.clip(AppShapes.card)
Expand Down Expand Up @@ -90,7 +92,10 @@ fun SelectionPill(
modifier = Modifier.padding(horizontal = 14.dp, vertical = 8.dp),
style = MaterialTheme.typography.labelLarge,
fontWeight = if (selected) FontWeight.Bold else FontWeight.Medium,
color = contentColor
color = contentColor,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
}
}
Expand Down Expand Up @@ -253,7 +258,8 @@ fun RemoteThumbnail(
modifier: Modifier = Modifier,
width: Dp = 72.dp,
height: Dp = 72.dp,
tint: Color = MaterialTheme.colorScheme.primary
tint: Color = MaterialTheme.colorScheme.primary,
contentDescription: String? = fallbackLabel
) {
val resolvedLabel = fallbackLabel.trim().firstOrNull()?.uppercase() ?: "G"
Box(
Expand Down Expand Up @@ -285,9 +291,9 @@ fun RemoteThumbnail(
} else {
SubcomposeAsyncImage(
model = imageModel,
contentDescription = null,
contentDescription = contentDescription,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
contentScale = ContentScale.Fit,
loading = {
Text(
text = resolvedLabel,
Expand Down Expand Up @@ -348,7 +354,10 @@ fun TextTabSelector(
text = label,
style = MaterialTheme.typography.labelLarge,
fontWeight = if (selected) FontWeight.Bold else FontWeight.Medium,
color = if (selected) tint else MaterialTheme.colorScheme.onSurfaceVariant
color = if (selected) tint else MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.height(8.dp))
Box(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ fun NativeImageGallery(
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
imageUrls.forEachIndexed { index, url ->
val imageLabel = stringResource(R.string.native_media_image_position, index + 1, imageUrls.size)
Column(
modifier = Modifier.width(cardWidth),
verticalArrangement = Arrangement.spacedBy(8.dp)
Expand All @@ -74,12 +75,12 @@ fun NativeImageGallery(
) {
SubcomposeAsyncImage(
model = url,
contentDescription = null,
contentDescription = imageLabel,
modifier = Modifier
.fillMaxWidth()
.height(cardHeight)
.clip(AppShapes.card),
contentScale = ContentScale.Crop,
contentScale = ContentScale.Fit,
loading = {
Box(
modifier = Modifier
Expand Down Expand Up @@ -113,7 +114,7 @@ fun NativeImageGallery(
)
}
Text(
text = stringResource(R.string.native_media_image_position, index + 1, imageUrls.size),
text = imageLabel,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Expand Down
102 changes: 102 additions & 0 deletions app/src/main/java/cn/gdeiassistant/ui/schedule/ScheduleScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ private fun ScheduleContent(
onCourseClick = { selectedCourse = it }
)
}
item {
ScheduleListCard(
state = state,
dayLabels = dayLabels,
onCourseClick = { selectedCourse = it }
)
}
}

if (showWeekPicker) {
Expand Down Expand Up @@ -716,6 +723,101 @@ private fun ScheduleGridCard(

private data class SchedulePlacement(val course: Schedule, val row: Int, val column: Int, val length: Int)

@Composable
private fun ScheduleListCard(
state: ScheduleUiState,
dayLabels: List<Int>,
onCourseClick: (Schedule) -> Unit
) {
SectionCard(modifier = Modifier.fillMaxWidth()) {
Text(
text = stringResource(R.string.schedule_list_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.schedule_list_subtitle),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(14.dp))
if (state.scheduleList.isEmpty()) {
Text(
text = stringResource(R.string.schedule_empty_grid),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
} else {
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
dayLabels.forEachIndexed { dayIndex, labelRes ->
val courses = state.coursesForDay(dayIndex)
if (courses.isNotEmpty()) {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text(
text = stringResource(labelRes),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary,
fontWeight = FontWeight.Bold
)
courses.forEach { course ->
ScheduleListRow(course = course, onClick = { onCourseClick(course) })
}
}
}
}
}
}
}
}

@Composable
private fun ScheduleListRow(course: Schedule, onClick: () -> Unit) {
Surface(
modifier = Modifier.fillMaxWidth(),
onClick = onClick,
shape = RoundedCornerShape(18.dp),
color = MaterialTheme.colorScheme.surfaceContainerLow
) {
Column(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
Text(
text = course.scheduleName ?: stringResource(R.string.schedule_course_unnamed),
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold,
lineHeight = MaterialTheme.typography.titleSmall.fontSize * 1.25f
)
Text(
text = listOfNotNull(
course.sectionDisplayText(),
course.scheduleLocation ?: stringResource(R.string.schedule_location_pending)
).joinToString(" · "),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = course.scheduleTeacher ?: stringResource(R.string.schedule_teacher_pending),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.tertiary
)
Text(
text = course.scheduleWeek
?: stringResource(
R.string.schedule_week_range,
course.minScheduleWeek ?: 1,
course.maxScheduleWeek ?: 1
),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}

// ──────────────────────────────────────────────────────────
// 对话框
// ──────────────────────────────────────────────────────────
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/cn/gdeiassistant/ui/theme/Type.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ val AppTypography = Typography(
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
letterSpacing = 0.sp
),
bodyMedium = TextStyle(
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.Normal,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
letterSpacing = 0.sp
),
// Specific style for numbers/data (e.g., grades, balance)
labelLarge = TextStyle(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
letterSpacing = 0.sp
)
)
2 changes: 2 additions & 0 deletions app/src/main/res/values-en/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@
<string name="schedule_focus_empty_other">No classes scheduled this week</string>
<string name="schedule_grid_title">Weekly Schedule</string>
<string name="schedule_grid_subtitle">Tap a class card to view location, instructor and weeks</string>
<string name="schedule_list_title">Full Course List</string>
<string name="schedule_list_subtitle">Grouped by day, with long names, locations and instructors shown in full.</string>
<string name="schedule_section_header">Section</string>
<string name="schedule_empty_grid">No classes scheduled this week</string>
<string name="schedule_select_week_title">Select Week</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@
<string name="schedule_focus_empty_other">今週は授業の予定がありません</string>
<string name="schedule_grid_title">週間時間割</string>
<string name="schedule_grid_subtitle">科目カードをタップすると教室・教員・対象週を確認できます</string>
<string name="schedule_list_title">全授業リスト</string>
<string name="schedule_list_subtitle">曜日ごとに表示し、長い科目名・教室・教員名も確認できます。</string>
<string name="schedule_section_header">コマ</string>
<string name="schedule_empty_grid">今週は授業の予定がありません</string>
<string name="schedule_select_week_title">週を選択</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-ko/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@
<string name="schedule_focus_empty_other">이번 주에는 수업 일정이 없습니다</string>
<string name="schedule_grid_title">주간 시간표</string>
<string name="schedule_grid_subtitle">수업 카드를 탭하면 장소, 교수 및 주차를 확인할 수 있습니다</string>
<string name="schedule_list_title">전체 수업 목록</string>
<string name="schedule_list_subtitle">요일별로 펼쳐 긴 수업명, 장소와 교수 정보를 확인할 수 있습니다.</string>
<string name="schedule_section_header">교시</string>
<string name="schedule_empty_grid">이번 주에는 수업 일정이 없습니다</string>
<string name="schedule_select_week_title">주차 선택</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-zh-rHK/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@
<string name="schedule_focus_empty_other">當前周還沒有課程安排</string>
<string name="schedule_grid_title">周課表</string>
<string name="schedule_grid_subtitle">點按課程卡片可查看上課地點、教師與周次</string>
<string name="schedule_list_title">完整課程列表</string>
<string name="schedule_list_subtitle">按星期展開,長課程名、地點和教師會完整顯示。</string>
<string name="schedule_section_header">節次</string>
<string name="schedule_empty_grid">當前周沒有課程安排</string>
<string name="schedule_select_week_title">選擇周數</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@
<string name="schedule_focus_empty_other">當前週還沒有課程安排</string>
<string name="schedule_grid_title">週課表</string>
<string name="schedule_grid_subtitle">點按課程卡片可查看上課地點、教師與週次</string>
<string name="schedule_list_title">完整課程列表</string>
<string name="schedule_list_subtitle">按星期展開,長課程名、地點和教師會完整顯示。</string>
<string name="schedule_section_header">節次</string>
<string name="schedule_empty_grid">當前週沒有課程安排</string>
<string name="schedule_select_week_title">選擇週數</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@
<string name="schedule_focus_empty_other">当前周还没有课程安排</string>
<string name="schedule_grid_title">周课表</string>
<string name="schedule_grid_subtitle">点按课程卡片可查看上课地点、教师与周次</string>
<string name="schedule_list_title">完整课程列表</string>
<string name="schedule_list_subtitle">按星期展开,长课程名、地点和教师会完整显示。</string>
<string name="schedule_section_header">节次</string>
<string name="schedule_empty_grid">当前周没有课程安排</string>
<string name="schedule_select_week_title">选择周数</string>
Expand Down