Skip to content

Commit 92a1547

Browse files
authored
Merge pull request #2700 from wgqqqqq/bitfun/refine-harmonyos-mobile-ui
feat(harmonyos): refine mobile UI and device navigation
2 parents 20ca614 + 6264207 commit 92a1547

41 files changed

Lines changed: 746 additions & 542 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

scripts/check-harmonyos-architecture.mjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ const conversationViewSource = fs.readFileSync(conversationViewPath, 'utf8');
202202
const conversationViewInputCount = [...conversationViewSource.matchAll(/^\s+@(Param|Event)\b/gm)].length;
203203
const wideConversationViewContract = conversationViewInputCount > 10 ?
204204
[`${relative(conversationViewPath)}:${conversationViewInputCount}`] : [];
205+
// SheetLayout may adapt cross-platform geometry for ArkUI, but it must not
206+
// become a second numeric source of truth for geometry already in the mobile
207+
// design contract. This deliberately checks ownership, not page-level sizes.
208+
const sheetLayoutPath = path.join(pagesRoot, 'components/SheetLayout.ets');
209+
const sheetLayoutSource = fs.readFileSync(sheetLayoutPath, 'utf8');
210+
const duplicateSheetGeometry =
211+
!sheetLayoutSource.includes("from '../../generated/MobileDesignTokens'") ||
212+
/export\s+const\s+SHEET_(?:HORIZONTAL_PADDING|HEADER_HEIGHT|ACTION_HEIGHT|TOP_RADIUS|SIDE_RADIUS)\s*:\s*number\s*=\s*\d/.test(
213+
sheetLayoutSource
214+
) ? [relative(sheetLayoutPath)] : [];
205215
const cryptoDeclarationPath = path.join(
206216
repoRoot,
207217
'src/apps/mobile/harmonyos/entry/src/main/cpp/types/libbitfun_crypto/index.d.ts'
@@ -402,6 +412,7 @@ const expected = {
402412
snapshottedMessageBuilderInput: [],
403413
missingObservableTimelineRows: [],
404414
wideConversationViewContract: [],
415+
duplicateSheetGeometry: [],
405416
synchronousArgon2Declaration: [],
406417
synchronousNativeArgon2: [],
407418
misplacedPresentationPolicies: []
@@ -440,6 +451,7 @@ const actual = {
440451
snapshottedMessageBuilderInput,
441452
missingObservableTimelineRows,
442453
wideConversationViewContract,
454+
duplicateSheetGeometry,
443455
synchronousArgon2Declaration,
444456
synchronousNativeArgon2,
445457
misplacedPresentationPolicies

src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/generated/MobileDesignTokens.kt

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import androidx.compose.ui.unit.sp
1010
internal object MobileDesignColors {
1111
object Light {
1212
val StartWindowBackground = Color(0xFFFFFFFF)
13-
val PageBg = Color(0xFFFDFDFB)
14-
val PageBgFade = Color(0x00FDFDFB)
13+
val PageBg = Color(0xFFFFFFFF)
14+
val PageBgFade = Color(0x00FFFFFF)
1515
val Ink = Color(0xFF171717)
1616
val Muted = Color(0xFF706F6A)
1717
val Subtle = Color(0xFFA5A39B)
@@ -87,7 +87,7 @@ internal object MobileDesignTypography {
8787
val HeadlineMedium = TextStyle(fontSize = 20.sp, lineHeight = 26.sp, fontWeight = FontWeight.Bold)
8888
val HeadlineSmall = TextStyle(fontSize = 18.sp, lineHeight = 24.sp, fontWeight = FontWeight.Bold)
8989
val TitleLarge = TextStyle(fontSize = 20.sp, lineHeight = 26.sp, fontWeight = FontWeight.Bold)
90-
val ConversationHeaderTitle = TextStyle(fontSize = 18.sp, lineHeight = 22.sp, fontWeight = FontWeight.Medium)
90+
val ConversationHeaderTitle = TextStyle(fontSize = 17.sp, lineHeight = 22.sp, fontWeight = FontWeight.Medium)
9191
val TitleMedium = TextStyle(fontSize = 17.sp, lineHeight = 22.sp, fontWeight = FontWeight.Medium)
9292
val TitleSmall = TextStyle(fontSize = 15.sp, lineHeight = 20.sp, fontWeight = FontWeight.Medium)
9393
val BodyLarge = TextStyle(fontSize = 16.sp, lineHeight = 24.sp, fontWeight = FontWeight.Normal)
@@ -101,34 +101,34 @@ internal object MobileDesignTypography {
101101
internal object MobileDesignGeometry {
102102
val ConversationHeaderHeight = 76.dp
103103
val ConversationHeaderCompactHeight = 64.dp
104-
val ControlTouchSize = 44.dp
104+
val ControlTouchSize = 48.dp
105105
val ContentGutter = 16.dp
106106
val ConnectionStripHeight = 48.dp
107107
val TimelineTopPadding = 22.dp
108-
val MessageSpacing = 12.dp
108+
val MessageSpacing = 18.dp
109109
val MessageBubbleMaxWidth = 276.dp
110110
val MessageBubbleHorizontalPadding = 14.dp
111111
val MessageBubbleVerticalPadding = 11.dp
112112
val MessageBubbleRadius = 17.dp
113-
val ComposerActionSize = 40.dp
114-
val ComposerInputHeight = 42.dp
115-
val ComposerExpandedInputHeight = 74.dp
116-
val ComposerCollapsedHeight = 52.dp
117-
val ComposerExpandedInputRowHeight = 76.dp
118-
val ComposerExpandedActionRowHeight = 44.dp
119-
val ComposerExpandedHeight = 126.dp
120-
val ComposerCollapsedRadius = 26.dp
113+
val ComposerActionSize = 44.dp
114+
val ComposerInputHeight = 44.dp
115+
val ComposerExpandedInputHeight = 58.dp
116+
val ComposerCollapsedHeight = 56.dp
117+
val ComposerExpandedInputRowHeight = 60.dp
118+
val ComposerExpandedActionRowHeight = 40.dp
119+
val ComposerExpandedHeight = 108.dp
120+
val ComposerCollapsedRadius = 28.dp
121121
val ComposerExpandedRadius = 18.dp
122122
val ComposerModelSelectorWidth = 330.dp
123123
val ComposerModelSelectorRadius = 14.dp
124124
val ComposerModelSelectorRowHeight = 48.dp
125125
val ComposerModelSelectorRowRadius = 9.dp
126126
val ComposerModelSelectorRowGap = 6.dp
127-
val SheetTopRadius = 34.dp
128-
val SheetSideRadius = 34.dp
127+
val SheetTopRadius = 28.dp
128+
val SheetSideRadius = 28.dp
129129
val SheetHorizontalPadding = 20.dp
130130
val SheetHeaderHeight = 56.dp
131-
val SheetActionHeight = 46.dp
131+
val SheetActionHeight = 48.dp
132132
val SelectionTopRadius = 20.dp
133133
val SelectionRowHeight = 64.dp
134134
val SelectionCloseSize = 32.dp
@@ -141,9 +141,9 @@ internal object MobileDesignGeometry {
141141
val CompactPopoverWidth = 150.dp
142142
val CompactPopoverRadius = 14.dp
143143
val CompactPopoverActionHeight = 42.dp
144-
val SettingsCompactCardRadius = 8.dp
145-
val SettingsCardRadius = 24.dp
146-
val SettingsProminentCardRadius = 28.dp
144+
val SettingsCompactCardRadius = 12.dp
145+
val SettingsCardRadius = 16.dp
146+
val SettingsProminentCardRadius = 20.dp
147147
val ModelCurrentRowHeight = 64.dp
148148
val ModelSourceRowHeight = 62.dp
149149
val ModelAccountRowHeight = 56.dp

src/apps/mobile/design-system/components/mobile-components.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
"version": 1,
33
"components": {
44
"circle_control": {
5-
"purpose": "A floating primary navigation or overflow control.",
6-
"anatomy": ["touch_target", "centered_glyph", "hairline_border", "soft_shadow"],
5+
"purpose": "A compact navigation or overflow control with a full-size touch target.",
6+
"anatomy": ["touch_target", "centered_glyph", "optional_pressed_surface"],
77
"states": ["enabled", "pressed", "disabled", "focused"],
88
"tokens": ["control_touch_size", "card", "line", "ink"],
9-
"platformNotes": "Keep the glyph's optical box separate from the touch target."
9+
"platformNotes": "Keep the glyph's optical box separate from the touch target. Header and sidebar controls stay visually transparent at rest; reserve borders and elevation for the containing surface."
10+
},
11+
"action_button": {
12+
"purpose": "Expresses one primary, secondary, quiet, or destructive workflow action with consistent emphasis.",
13+
"anatomy": ["touch_target", "action_label", "semantic_surface", "optional_hairline_border"],
14+
"states": ["primary", "secondary", "quiet", "destructive", "disabled", "busy"],
15+
"tokens": ["sheet_action_height", "primary_action", "primary_action_text", "card", "soft", "line", "red", "label_large"],
16+
"platformNotes": "The semantic style is shared; a workflow may override height when its context requires a larger target, while preserving typography, radius, color, and disabled treatment."
1017
},
1118
"conversation_header": {
1219
"purpose": "Identifies the active conversation and the device or workspace answering it.",
@@ -27,7 +34,7 @@
2734
"anatomy": ["attachment_action", "text_input", "model_control", "primary_action"],
2835
"states": ["empty", "draft", "focused", "streaming", "disconnected", "with_attachments"],
2936
"tokens": ["composer_action_size", "composer_collapsed_height", "composer_expanded_height", "composer_collapsed_radius", "composer_expanded_radius"],
30-
"platformNotes": "Keyboard, dictation, and attachment pickers remain native adapters."
37+
"platformNotes": "Keyboard, dictation, and attachment pickers remain native adapters. The focused two-row form stays compact and exists to expose message context controls; multiline content and attachments may grow it further. The trailing action is the single filled action for Send, Dictate, or Stop."
3138
},
3239
"composer_model_selector": {
3340
"purpose": "Changes the model for the message being composed without leaving the conversation or creation flow.",

src/apps/mobile/design-system/preview/generated/mobile-design-data.js

Lines changed: 52 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/apps/mobile/design-system/tokens/mobile-tokens.json

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
},
77
"colors": {
88
"start_window_background": { "light": "#FFFFFF", "dark": "#000000" },
9-
"page_bg": { "light": "#FDFDFB", "dark": "#151514" },
10-
"page_bg_fade": { "light": "#00FDFDFB", "dark": "#00151514" },
9+
"page_bg": { "light": "#FFFFFF", "dark": "#151514" },
10+
"page_bg_fade": { "light": "#00FFFFFF", "dark": "#00151514" },
1111
"ink": { "light": "#171717", "dark": "#F4F3EF" },
1212
"muted": { "light": "#706F6A", "dark": "#AAA8A0" },
1313
"subtle": { "light": "#A5A39B", "dark": "#77756E" },
@@ -46,7 +46,7 @@
4646
"headline_medium": { "size": 20, "lineHeight": 26, "weight": 700 },
4747
"headline_small": { "size": 18, "lineHeight": 24, "weight": 700 },
4848
"title_large": { "size": 20, "lineHeight": 26, "weight": 700 },
49-
"conversation_header_title": { "size": 18, "lineHeight": 22, "weight": 500 },
49+
"conversation_header_title": { "size": 17, "lineHeight": 22, "weight": 600 },
5050
"title_medium": { "size": 17, "lineHeight": 22, "weight": 500 },
5151
"title_small": { "size": 15, "lineHeight": 20, "weight": 500 },
5252
"body_large": { "size": 16, "lineHeight": 24, "weight": 400 },
@@ -59,34 +59,34 @@
5959
"geometry": {
6060
"conversation_header_height": 76,
6161
"conversation_header_compact_height": 64,
62-
"control_touch_size": 44,
62+
"control_touch_size": 48,
6363
"content_gutter": 16,
6464
"connection_strip_height": 48,
6565
"timeline_top_padding": 22,
66-
"message_spacing": 12,
66+
"message_spacing": 18,
6767
"message_bubble_max_width": 276,
6868
"message_bubble_horizontal_padding": 14,
6969
"message_bubble_vertical_padding": 11,
7070
"message_bubble_radius": 17,
71-
"composer_action_size": 40,
72-
"composer_input_height": 42,
73-
"composer_expanded_input_height": 74,
74-
"composer_collapsed_height": 52,
75-
"composer_expanded_input_row_height": 76,
76-
"composer_expanded_action_row_height": 44,
77-
"composer_expanded_height": 126,
78-
"composer_collapsed_radius": 26,
71+
"composer_action_size": 44,
72+
"composer_input_height": 44,
73+
"composer_expanded_input_height": 58,
74+
"composer_collapsed_height": 56,
75+
"composer_expanded_input_row_height": 60,
76+
"composer_expanded_action_row_height": 40,
77+
"composer_expanded_height": 108,
78+
"composer_collapsed_radius": 28,
7979
"composer_expanded_radius": 18,
8080
"composer_model_selector_width": 330,
8181
"composer_model_selector_radius": 14,
8282
"composer_model_selector_row_height": 48,
8383
"composer_model_selector_row_radius": 9,
8484
"composer_model_selector_row_gap": 6,
85-
"sheet_top_radius": 34,
86-
"sheet_side_radius": 34,
85+
"sheet_top_radius": 28,
86+
"sheet_side_radius": 28,
8787
"sheet_horizontal_padding": 20,
8888
"sheet_header_height": 56,
89-
"sheet_action_height": 46,
89+
"sheet_action_height": 48,
9090
"selection_top_radius": 20,
9191
"selection_row_height": 64,
9292
"selection_close_size": 32,
@@ -99,9 +99,9 @@
9999
"compact_popover_width": 150,
100100
"compact_popover_radius": 14,
101101
"compact_popover_action_height": 42,
102-
"settings_compact_card_radius": 8,
103-
"settings_card_radius": 24,
104-
"settings_prominent_card_radius": 28,
102+
"settings_compact_card_radius": 12,
103+
"settings_card_radius": 16,
104+
"settings_prominent_card_radius": 20,
105105
"model_current_row_height": 64,
106106
"model_source_row_height": 62,
107107
"model_account_row_height": 56,

0 commit comments

Comments
 (0)