Skip to content

Revert "Revert "Rewrite profile module as schedule management hub with iCalendar import/export and network subscriptions""#3

Merged
Owl23007 merged 1 commit into
masterfrom
revert-2-revert-1-copilot/update-profile-module-schedule
Jan 23, 2026
Merged

Revert "Revert "Rewrite profile module as schedule management hub with iCalendar import/export and network subscriptions""#3
Owl23007 merged 1 commit into
masterfrom
revert-2-revert-1-copilot/update-profile-module-schedule

Conversation

@Owl23007
Copy link
Copy Markdown
Owner

Reverts #2

…h iCalendar import/export and network subscriptions""
Copilot AI review requested due to automatic review settings January 23, 2026 07:08
@Owl23007 Owl23007 merged commit 1fba9b6 into master Jan 23, 2026
5 checks passed
@Owl23007 Owl23007 deleted the revert-2-revert-1-copilot/update-profile-module-schedule branch January 23, 2026 07:09
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reverts a previous revert, effectively re-introducing a comprehensive rewrite of the Profile module into a schedule management hub. The changes add iCalendar import/export functionality and network calendar subscription support across domain, data, and feature layers.

Changes:

  • Adds 7 new use cases in the domain layer for schedule import/export and subscription management (CRUD operations and sync)
  • Implements 2 new services in the data layer: ICalendarService for RFC 5545 format conversion and SubscriptionSyncService for network synchronization
  • Completely rewrites ProfileViewModel and ProfileScreen to focus on schedule management instead of user profile features

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
gradlew Adds standard Gradle wrapper script (entire file addition)
domain/.../ImportScheduleUseCase.kt New use case for importing schedules from iCalendar format with conflict resolution strategies
domain/.../ExportScheduleUseCase.kt New use case for exporting schedules to iCalendar format
domain/.../SyncSubscriptionUseCase.kt New use case for syncing network calendar subscriptions (placeholder implementation)
domain/.../GetAllSubscriptionsUseCase.kt New use case for querying subscription data
domain/.../CreateSubscriptionUseCase.kt New use case for creating calendar subscriptions with URL validation
domain/.../DeleteSubscriptionUseCase.kt New use case for deleting subscriptions and their associated schedules
domain/.../UpdateSubscriptionUseCase.kt New use case for updating subscription settings (name, URL, sync interval, enabled status)
data/.../ICalendarService.kt New service implementing biweekly library for iCalendar parsing and generation
data/.../SubscriptionSyncService.kt New service for fetching and parsing network calendar subscriptions via HTTP
data/build.gradle.kts Adds biweekly and okhttp dependencies
feature/profile/.../ProfileViewModel.kt Rewrites ViewModel to handle schedule management actions and subscription state
feature/profile/.../ProfileScreen.kt Rewrites UI to display subscriptions, schedule tools, and management dialogs
TEST_REPORT.md Adds testing report claiming all issues fixed and architecture compliance
RELEASE_NOTES.md Adds comprehensive release notes documenting new features and technical details
GITHUB_RELEASE_NOTE.md Adds GitHub-formatted release notes for publishing
.github/workflows/release-apk.yml Fixes heredoc syntax in changelog generation

successCount++
}
} catch (e: Exception) {
android.util.Log.e("ImportScheduleUseCase", "导入日程失败: ${schedule.id}", e)
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The domain layer should not depend on Android-specific classes. The use of android.util.Log violates Clean Architecture principles. The domain layer must remain pure Kotlin to maintain testability and platform independence. Consider using a logging abstraction interface that can be injected, or remove the logging from the domain layer entirely and handle logging in the data or presentation layers.

Suggested change
android.util.Log.e("ImportScheduleUseCase", "导入日程失败: ${schedule.id}", e)

Copilot uses AI. Check for mistakes.
try {
deleteSubscriptionUseCase(subscriptionId)
} catch (e: Exception) {
_scheduleAction.value = ScheduleManagementAction.ImportError(
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ImportError action type for delete subscription errors is misleading. This should use a more appropriate action type or a generic error action type. The reuse of ImportError for different operations will confuse users and developers about the actual operation that failed.

Suggested change
_scheduleAction.value = ScheduleManagementAction.ImportError(
_scheduleAction.value = ScheduleManagementAction.SyncError(

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +59

// 处理日程操作结果
LaunchedEffect(scheduleAction) {
// 如需要可处理不同的操作状态
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LaunchedEffect block is empty with only a comment suggesting future handling. This creates dead code that serves no current purpose. Either implement the handling logic now or remove this LaunchedEffect until it's needed.

Suggested change
// 处理日程操作结果
LaunchedEffect(scheduleAction) {
// 如需要可处理不同的操作状态
}

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +60
return try {
val uri = java.net.URI(url)
uri.scheme in listOf("http", "https", "webcal")
} catch (e: Exception) {
false
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function uses java.net.URI for URL validation, which is Java-specific. Since the domain layer should remain pure Kotlin, consider using kotlin.io or other pure Kotlin alternatives for URL validation, or move this validation logic to the data layer where platform-specific code is acceptable.

Suggested change
return try {
val uri = java.net.URI(url)
uri.scheme in listOf("http", "https", "webcal")
} catch (e: Exception) {
false
}
// 使用纯 Kotlin 的正则表达式进行基本 URL 校验,限制为 http/https/webcal 协议
val pattern = Regex("^(https?|webcal)://.+$")
return pattern.matches(url.trim())

Copilot uses AI. Check for mistakes.
require(isValidUrl(url)) { "URL 格式无效" }

val subscription = Subscription(
id = UUID.randomUUID().toString(),
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using java.util.UUID directly in the domain layer introduces a Java dependency. Consider using a UUID generation abstraction or moving UUID generation to the repository layer to keep the domain layer pure Kotlin and more testable.

Copilot uses AI. Check for mistakes.
syncInterval = syncInterval
)
} catch (e: Exception) {
_scheduleAction.value = ScheduleManagementAction.ImportError(
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ImportError action type for create subscription errors is misleading. This should use a more appropriate action type or a generic error action type. The reuse of ImportError for different operations will confuse users and developers about the actual operation that failed.

Copilot uses AI. Check for mistakes.
Comment on lines +371 to +374
text = "最后同步: ${remember(it) {
java.text.SimpleDateFormat("yyyy-MM-dd HH:mm", java.util.Locale.getDefault())
.format(java.util.Date(it))
}}",
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using java.text.SimpleDateFormat and java.util.Date directly in Compose UI code creates unnecessary object creation on every recomposition. While the remember block helps, consider using a date formatting utility function or androidx.compose.ui.text formatting utilities for better performance and consistency across the app.

Copilot uses AI. Check for mistakes.
Comment on lines +505 to +528
@Composable
fun ImportExportDialog(
onDismiss: () -> Unit,
viewModel: ProfileViewModel
) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text("导入导出") },
text = {
Column {
Text("日程导入导出功能")
Spacer(modifier = Modifier.height(8.dp))
Text("• 支持iCalendar (.ics)格式", fontSize = 12.sp)
Text("• 可从文件导入日程", fontSize = 12.sp)
Text("• 可导出日程到文件", fontSize = 12.sp)
}
},
confirmButton = {
TextButton(onClick = onDismiss) {
Text("关闭")
}
}
)
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ImportExportDialog shows static information but doesn't provide any actual functionality to import or export schedules. The dialog only displays what features are supported but has no buttons or actions to trigger import/export operations. Users will be confused by a dialog that describes functionality without providing a way to use it.

Copilot uses AI. Check for mistakes.
Comment thread RELEASE_NOTES.md
Comment on lines +15 to +21
### 1. 日程导入导出
- ✅ **iCalendar 格式支持**:完全符合 RFC 5545 标准
- ✅ **导出功能**:将日程导出为 .ics 文件
- ✅ **导入功能**:从 .ics 文件导入日程
- ✅ **冲突处理**:支持三种策略(跳过、替换、保留两者)
- ✅ **全天事件**:正确处理全天事件
- ✅ **时区支持**:保留和提取时区信息
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The release notes claim that the import/export functionality is fully implemented with checkmarks, but the ImportExportDialog only displays informational text without any actual import or export actions. The UI provides no way for users to select files to import or trigger exports, making these listed features non-functional in the current implementation.

Copilot uses AI. Check for mistakes.
Comment on lines +363 to +368
Text(
text = subscription.url,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1
)
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subscription URL text has maxLines = 1 but is missing overflow = TextOverflow.Ellipsis. Without the overflow parameter, long URLs will be cut off abruptly without any visual indication that there's more text. This creates poor UX as users won't know if the URL is complete or truncated.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants