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
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@
<string name="chat_antigravity_signin">使用 Google 登录</string>
<string name="chat_antigravity_waiting">正在等待浏览器 — 授权后请返回 CodeAssist</string>
<string name="chat_cancel">取消</string>

<string name="chat_ca_cert">CA 证书(可选)</string>

<string name="chat_ca_cert_hint">仅当端点使用系统不信任的私有或区域性 CA 时(如 GigaChat)才粘贴 CA 证书(PEM)。它会在系统 CA 之外额外受信任;证书链仍会校验。</string>
</resources>
859 changes: 859 additions & 0 deletions ide-ui/src/commonMain/composeResources/values-zh/strings.xml

Large diffs are not rendered by default.

159 changes: 159 additions & 0 deletions ide-ui/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1604,4 +1604,163 @@ We never collect your code, file or project names, which features you use, or an
<string name="icons_reference">Reference</string>
<string name="icons_app_icon_short">App icon</string>
<string name="icons_no_repositories">No icon libraries are registered.</string>

<string name="action_close_project">Close project</string>

<string name="action_close_project_desc">Back to all projects</string>

<string name="action_dependencies">Manage dependencies</string>

<string name="action_hub">Settings &amp; Tools</string>

<string name="action_hub_desc">Settings · code style · SDK manager · keystore manager</string>

<string name="action_icons">Icon Manager</string>

<string name="action_icons_desc">Browse and import icons, and change the app icon</string>

<string name="action_logs">View logs</string>

<string name="action_logs_desc">Editor, analysis &amp; build logs — share when something's off</string>

<string name="action_modules">Modules</string>

<string name="action_modules_desc">Add/remove modules · Java version · dependencies · repositories</string>

<string name="action_reindex">Re-index project</string>

<string name="action_reindex_desc">Rebuild symbol &amp; completion indexes</string>

<string name="action_toggle_theme">Toggle theme</string>

<string name="action_toggle_theme_desc">Switch between light and dark</string>

<string name="store_action_read_why">Read why</string>

<string name="store_action_use">Use</string>

<string name="store_action_view_listing">View listing</string>

<string name="store_action_view_notes">View notes</string>

<string name="store_action_withdraw">Withdraw</string>

<string name="store_badge_cd">%1$d projects published</string>

<string name="store_badge_first">FIRST ON THE SHELF</string>

<string name="store_badge_new">NEW</string>

<string name="store_bundled_subtitle">Offline scaffolds that ship with the install.</string>

<string name="store_bundled_title">Bundled with your IDE</string>

<string name="store_catalogue_subtitle">newest first</string>

<string name="store_collections_title">Collections</string>

<string name="store_empty_hero_body">Templates, sample apps and plugins show up here the moment they pass review. Yours can be the first one.</string>

<string name="store_empty_hero_title">No one has published a project yet</string>

<string name="store_ghost_charts_note">Ranks appear once projects have a week of install history.</string>

<string name="store_ghost_collections_note">Curated shelves are assembled by the team from published projects.</string>

<string name="store_ghost_count_cd">%1$d of %2$d projects needed</string>

<string name="store_ghost_next_title">What lands here next</string>

<string name="store_ghost_recommend_note">Recommendations need your install history — install something first.</string>

<string name="store_ghost_section_subtitle">Each shelf switches on when it has enough to rank.</string>

<string name="store_ghost_section_title">What unlocks as the store grows</string>

<string name="store_ghostspec_charts_note">Ranking starts at %1$d projects — a chart of four is just the list above.</string>

<string name="store_ghostspec_collections_note">The team builds a collection once there are enough projects to theme one.</string>

<string name="store_ghostspec_rec_note">Recommendations need install history across several projects.</string>

<string name="store_ghostspec_rec_title">Because you installed…</string>

<string name="store_hero_eyebrow_open">The store is open</string>

<string name="store_how_it_works">How it works</string>

<string name="store_how_publishing_title">How publishing works</string>

<string name="store_meta_offline">offline</string>

<string name="store_not_rated">Not rated yet</string>

<string name="store_notify_state_off">Notifications off</string>

<string name="store_notify_state_on">Notifications on</string>

<string name="store_notify_subtitle">One notification, only for the first batch.</string>

<string name="store_notify_title">Tell me when projects arrive</string>

<string name="store_ordinal_fifth">fifth</string>

<string name="store_ordinal_fourth">fourth</string>

<string name="store_ordinal_second">second</string>

<string name="store_ordinal_third">third</string>

<string name="store_perk_direct_line">Direct line to the review team</string>

<string name="store_perk_front_page">Front page from day one</string>

<string name="store_pitch_body">Everything published right now sits on this page — no ranking to climb, no back pages to fall into. That stops being true later.</string>

<string name="store_pitch_eyebrow">Shelves are still short</string>

<string name="store_pitch_next">%1$s Yours would be next.</string>

<string name="store_pitch_ordinal_full">%1$s Yours would be the %2$s.</string>

<string name="store_pitch_subject">%1$d projects in.</string>

<string name="store_pitch_subject_one">One project in.</string>

<string name="store_publish_another">Publish another</string>

<string name="store_publish_cta">Publish a project</string>

<string name="store_publishing_guide">Publishing guide</string>

<string name="store_status_building">Building on a clean machine</string>

<string name="store_status_changes">Changes requested — read the notes</string>

<string name="store_status_published">Live in the store</string>

<string name="store_status_rejected">Not accepted</string>

<string name="store_status_rejected_note">Not accepted · %1$s</string>

<string name="store_status_submitted">In review · usually 2 business days</string>

<string name="store_step_listing_body">Title, a short description, category and screenshots — captured from your editor inside the app.</string>

<string name="store_step_listing_title">Fill in the listing</string>

<string name="store_step_pick_body">Choose any local project. CodeAssist reads its name, language, JDK and Gradle setup for you — nothing to write by hand.</string>

<string name="store_step_pick_title">Pick a project from Home</string>

<string name="store_step_submit_body">We build it on a clean machine and a human checks licensing and the README. Usually two business days.</string>

<string name="store_step_submit_title">Submit for review</string>

<string name="store_top_charts">Top charts</string>

<plurals name="store_project_count">
<item quantity="one">%1$d PROJECT</item>
<item quantity="other">%1$d PROJECTS</item>
</plurals>
</resources>
107 changes: 81 additions & 26 deletions ide-ui/src/commonMain/kotlin/dev/ide/ui/components/StoreEmpty.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,37 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import dev.ide.ui.backend.UiStoreSubmission
import dev.ide.ui.backend.UiSubmissionStatus
import dev.ide.ui.generated.resources.Res
import dev.ide.ui.generated.resources.store_empty_hero_body
import dev.ide.ui.generated.resources.store_empty_hero_title
import dev.ide.ui.generated.resources.store_ghost_charts_note
import dev.ide.ui.generated.resources.store_ghost_collections_note
import dev.ide.ui.generated.resources.store_ghost_recommend_note
import dev.ide.ui.generated.resources.store_hero_eyebrow_open
import dev.ide.ui.generated.resources.store_notify_state_off
import dev.ide.ui.generated.resources.store_notify_state_on
import dev.ide.ui.generated.resources.store_notify_subtitle
import dev.ide.ui.generated.resources.store_notify_title
import dev.ide.ui.generated.resources.store_publish_another
import dev.ide.ui.generated.resources.store_publish_cta
import dev.ide.ui.generated.resources.store_publishing_guide
import dev.ide.ui.generated.resources.store_action_read_why
import dev.ide.ui.generated.resources.store_action_view_listing
import dev.ide.ui.generated.resources.store_action_view_notes
import dev.ide.ui.generated.resources.store_action_withdraw
import dev.ide.ui.generated.resources.store_status_building
import dev.ide.ui.generated.resources.store_status_changes
import dev.ide.ui.generated.resources.store_status_published
import dev.ide.ui.generated.resources.store_status_rejected
import dev.ide.ui.generated.resources.store_status_rejected_note
import dev.ide.ui.generated.resources.store_status_submitted
import dev.ide.ui.generated.resources.store_step_listing_body
import dev.ide.ui.generated.resources.store_step_listing_title
import dev.ide.ui.generated.resources.store_step_pick_body
import dev.ide.ui.generated.resources.store_step_pick_title
import dev.ide.ui.generated.resources.store_step_submit_body
import dev.ide.ui.generated.resources.store_step_submit_title
import org.jetbrains.compose.resources.stringResource
import dev.ide.ui.icons.CaSymbols
import dev.ide.ui.theme.Symbol
import dev.ide.ui.theme.tileShape
Expand Down Expand Up @@ -85,9 +116,9 @@ fun EmptyStoreHero(
modifier = Modifier.align(Alignment.BottomEnd).offset(x = 24.dp, y = 34.dp),
)
Column(Modifier.padding(horizontal = 20.dp, vertical = 24.dp)) {
Eyebrow("The store is open", color = c.onPrimaryContainer.copy(alpha = 0.75f))
Eyebrow(stringResource(Res.string.store_hero_eyebrow_open), color = c.onPrimaryContainer.copy(alpha = 0.75f))
Text(
"No one has published a project yet",
stringResource(Res.string.store_empty_hero_title),
style = MaterialTheme.typography.headlineMedium.copy(
fontWeight = FontWeight.Medium, fontSize = 26.sp, lineHeight = 32.sp,
letterSpacing = (-0.7).sp,
Expand All @@ -96,8 +127,7 @@ fun EmptyStoreHero(
modifier = Modifier.padding(top = 8.dp),
)
Text(
"Templates, sample apps and plugins show up here the moment they pass review. " +
"Yours can be the first one.",
stringResource(Res.string.store_empty_hero_body),
style = MaterialTheme.typography.bodyMedium,
color = c.onPrimaryContainer.copy(alpha = 0.82f),
modifier = Modifier.padding(top = 10.dp),
Expand All @@ -121,7 +151,11 @@ fun EmptyStoreHero(
) {
Symbol(CaSymbols.upload, contentDescription = null, size = 20.dp)
Text(
if (hasSubmission) "Publish another" else "Publish a project",
if (hasSubmission) {
stringResource(Res.string.store_publish_another)
} else {
stringResource(Res.string.store_publish_cta)
},
style = MaterialTheme.typography.labelLarge,
)
}
Expand All @@ -135,7 +169,7 @@ fun EmptyStoreHero(
modifier = Modifier.height(46.dp),
) {
Box(Modifier.padding(horizontal = 20.dp), contentAlignment = Alignment.Center) {
Text("Publishing guide", style = MaterialTheme.typography.labelLarge)
Text(stringResource(Res.string.store_publishing_guide), style = MaterialTheme.typography.labelLarge)
}
}
}
Expand Down Expand Up @@ -189,19 +223,19 @@ fun PublishingSteps(steps: List<PublishStep>, modifier: Modifier = Modifier) {
}

/** The default copy for [PublishingSteps]. Kept beside the component so the two cannot drift apart. */
val defaultPublishSteps: List<PublishStep> = listOf(
@Composable
fun defaultPublishSteps(): List<PublishStep> = listOf(
PublishStep(
"Pick a project from Home",
"Choose any local project. CodeAssist reads its name, language, JDK and Gradle setup for you — " +
"nothing to write by hand.",
stringResource(Res.string.store_step_pick_title),
stringResource(Res.string.store_step_pick_body),
),
PublishStep(
"Fill in the listing",
"Title, a short description, category and screenshots — captured from your editor inside the app.",
stringResource(Res.string.store_step_listing_title),
stringResource(Res.string.store_step_listing_body),
),
PublishStep(
"Submit for review",
"We build it on a clean machine and a human checks licensing and the README. Usually two business days.",
stringResource(Res.string.store_step_submit_title),
stringResource(Res.string.store_step_submit_body),
),
)

Expand All @@ -225,6 +259,9 @@ fun NotifySwitchRow(
message: String? = null,
) {
val c = MaterialTheme.colorScheme
// Resolved outside the semantics block: stringResource is composable-only.
val stateOn = stringResource(Res.string.store_notify_state_on)
val stateOff = stringResource(Res.string.store_notify_state_off)
Surface(
shape = RoundedCornerShape(26.dp),
color = c.surfaceContainerLow,
Expand All @@ -238,12 +275,12 @@ fun NotifySwitchRow(
) {
Column(Modifier.weight(1f)) {
Text(
"Tell me when projects arrive",
stringResource(Res.string.store_notify_title),
style = MaterialTheme.typography.titleSmall,
color = c.onSurface,
)
Text(
message ?: "One notification, only for the first batch.",
message ?: stringResource(Res.string.store_notify_subtitle),
style = MaterialTheme.typography.bodySmall,
// The failure takes over the supporting line rather than adding a row: it replaces the
// promise it just failed to keep.
Expand All @@ -257,7 +294,7 @@ fun NotifySwitchRow(
checked = checked,
onCheckedChange = onCheckedChange,
modifier = Modifier.semantics {
stateDescription = if (checked) "Notifications on" else "Notifications off"
stateDescription = if (checked) stateOn else stateOff
},
)
}
Expand All @@ -282,19 +319,36 @@ fun SubmissionStatusCard(
val c = MaterialTheme.colorScheme
val (line, actionLabel, action) = when (submission.status) {
UiSubmissionStatus.SUBMITTED ->
Triple("In review · usually 2 business days", "Withdraw", onWithdraw)
Triple(
stringResource(Res.string.store_status_submitted),
stringResource(Res.string.store_action_withdraw),
onWithdraw,
)
UiSubmissionStatus.BUILDING ->
Triple("Building on a clean machine", "Withdraw", onWithdraw)
Triple(
stringResource(Res.string.store_status_building),
stringResource(Res.string.store_action_withdraw),
onWithdraw,
)
UiSubmissionStatus.CHANGES_REQUESTED ->
Triple("Changes requested — read the notes", "View notes", onViewNotes)
Triple(
stringResource(Res.string.store_status_changes),
stringResource(Res.string.store_action_view_notes),
onViewNotes,
)
UiSubmissionStatus.REJECTED ->
Triple(
submission.note?.let { "Not accepted · $it" } ?: "Not accepted",
"Read why",
submission.note?.let { stringResource(Res.string.store_status_rejected_note, it) }
?: stringResource(Res.string.store_status_rejected),
stringResource(Res.string.store_action_read_why),
onViewNotes,
)
UiSubmissionStatus.PUBLISHED ->
Triple("Live in the store", "View listing", onViewListing)
Triple(
stringResource(Res.string.store_status_published),
stringResource(Res.string.store_action_view_listing),
onViewListing,
)
}
// Only the in-flight states spin; a finished one holding an animation would read as still working.
val spinning = submission.status == UiSubmissionStatus.SUBMITTED ||
Expand Down Expand Up @@ -376,8 +430,9 @@ private fun SpinningGlyph(glyph: Char, spinning: Boolean, tint: Color) {
* Different from the sparse state's on purpose: with nothing published, the honest thing to state is the
* **condition** that fills the shelf, not a threshold the reader is nowhere near.
*/
@Composable
fun emptyGhostNote(key: String): String = when (key) {
"charts" -> "Ranks appear once projects have a week of install history."
"collections" -> "Curated shelves are assembled by the team from published projects."
else -> "Recommendations need your install history — install something first."
"charts" -> stringResource(Res.string.store_ghost_charts_note)
"collections" -> stringResource(Res.string.store_ghost_collections_note)
else -> stringResource(Res.string.store_ghost_recommend_note)
}
Loading