chore: 更新国际化翻译及 UI 组件优化
This commit is contained in:
@@ -8,6 +8,10 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
final Color g3Text, g3Divider, g3Border;
|
||||
final Color eventDefault;
|
||||
final Color eventArchived;
|
||||
final Color warning;
|
||||
final Color warningContainer;
|
||||
final Color onWarning;
|
||||
final Color onWarningContainer;
|
||||
|
||||
const AppColorPalette({
|
||||
required this.eventPresetColors,
|
||||
@@ -23,6 +27,10 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
required this.g3Border,
|
||||
required this.eventDefault,
|
||||
required this.eventArchived,
|
||||
required this.warning,
|
||||
required this.warningContainer,
|
||||
required this.onWarning,
|
||||
required this.onWarningContainer,
|
||||
});
|
||||
|
||||
static const light = AppColorPalette(
|
||||
@@ -51,6 +59,10 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
g3Border: Color(0xFFCFE1FB),
|
||||
eventDefault: Color(0xFF3B82F6),
|
||||
eventArchived: Color(0xFF64748B),
|
||||
warning: Color(0xFFF59E0B),
|
||||
warningContainer: Color(0xFFFEF3C7),
|
||||
onWarning: Color(0xFFFFFFFF),
|
||||
onWarningContainer: Color(0xFF78350F),
|
||||
);
|
||||
|
||||
static const dark = AppColorPalette(
|
||||
@@ -79,6 +91,10 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
g3Border: Color(0xFF2563EB),
|
||||
eventDefault: Color(0xFF60A5FA),
|
||||
eventArchived: Color(0xFF94A3B8),
|
||||
warning: Color(0xFFFBBF24),
|
||||
warningContainer: Color(0xFF78350F),
|
||||
onWarning: Color(0xFF0F172A),
|
||||
onWarningContainer: Color(0xFFFEF3C7),
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -96,6 +112,10 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
Color? g3Border,
|
||||
Color? eventDefault,
|
||||
Color? eventArchived,
|
||||
Color? warning,
|
||||
Color? warningContainer,
|
||||
Color? onWarning,
|
||||
Color? onWarningContainer,
|
||||
}) {
|
||||
return AppColorPalette(
|
||||
eventPresetColors: eventPresetColors ?? this.eventPresetColors,
|
||||
@@ -111,6 +131,10 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
g3Border: g3Border ?? this.g3Border,
|
||||
eventDefault: eventDefault ?? this.eventDefault,
|
||||
eventArchived: eventArchived ?? this.eventArchived,
|
||||
warning: warning ?? this.warning,
|
||||
warningContainer: warningContainer ?? this.warningContainer,
|
||||
onWarning: onWarning ?? this.onWarning,
|
||||
onWarningContainer: onWarningContainer ?? this.onWarningContainer,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -139,6 +163,18 @@ class AppColorPalette extends ThemeExtension<AppColorPalette> {
|
||||
g3Border: Color.lerp(g3Border, other.g3Border, t)!,
|
||||
eventDefault: Color.lerp(eventDefault, other.eventDefault, t)!,
|
||||
eventArchived: Color.lerp(eventArchived, other.eventArchived, t)!,
|
||||
warning: Color.lerp(warning, other.warning, t)!,
|
||||
warningContainer: Color.lerp(
|
||||
warningContainer,
|
||||
other.warningContainer,
|
||||
t,
|
||||
)!,
|
||||
onWarning: Color.lerp(onWarning, other.onWarning, t)!,
|
||||
onWarningContainer: Color.lerp(
|
||||
onWarningContainer,
|
||||
other.onWarningContainer,
|
||||
t,
|
||||
)!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ String? mapErrorCodeToL10nKey(
|
||||
return 'errorGenericSafe';
|
||||
case 'AGENT_RUN_MESSAGES_INVALID':
|
||||
return 'errorGenericSafe';
|
||||
case 'AGENT_INVALID_RUN_ID':
|
||||
return 'errorGenericSafe';
|
||||
case 'AGENT_INVALID_LAST_EVENT_ID':
|
||||
return 'errorAgentInvalidLastEventId';
|
||||
case 'AGENT_SSE_CONNECTION_LIMIT':
|
||||
|
||||
@@ -41,8 +41,6 @@ class LoginView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LoginViewState extends State<LoginView> {
|
||||
static const _dialCodes = <String>['+86', '+1', '+44', '+81', '+65'];
|
||||
|
||||
final _phoneController = TextEditingController();
|
||||
final _codeController = TextEditingController();
|
||||
bool _agreedToTerms = false;
|
||||
@@ -230,7 +228,6 @@ class _LoginViewState extends State<LoginView> {
|
||||
keyboardType: TextInputType.phone,
|
||||
prefix: PhonePrefixSelector(
|
||||
value: state.dialCode,
|
||||
items: _dialCodes,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<LoginCubit>()
|
||||
|
||||
@@ -113,13 +113,15 @@ class FriendRequestResponse {
|
||||
});
|
||||
|
||||
factory FriendRequestResponse.fromJson(Map<String, dynamic> json) {
|
||||
final rawContent = json['content'] as Map<String, dynamic>?;
|
||||
final content = rawContent?['message'] as String?;
|
||||
return FriendRequestResponse(
|
||||
id: json['id'] as String,
|
||||
sender: UserBasicInfo.fromJson(json['sender'] as Map<String, dynamic>),
|
||||
recipient: UserBasicInfo.fromJson(
|
||||
json['recipient'] as Map<String, dynamic>,
|
||||
),
|
||||
content: json['content'] as String?,
|
||||
content: content,
|
||||
status: json['status'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
);
|
||||
|
||||
@@ -38,11 +38,13 @@ class FriendRequest {
|
||||
});
|
||||
|
||||
factory FriendRequest.fromJson(Map<String, dynamic> json) {
|
||||
final rawContent = json['content'] as Map<String, dynamic>?;
|
||||
final content = rawContent?['message'] as String?;
|
||||
return FriendRequest(
|
||||
id: json['id'] as String,
|
||||
sender: FriendUser.fromJson(json['sender'] as Map<String, dynamic>),
|
||||
recipient: FriendUser.fromJson(json['recipient'] as Map<String, dynamic>),
|
||||
content: json['content'] as String?,
|
||||
content: content,
|
||||
status: _friendRequestStatusFromApi(json['status'] as String),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
);
|
||||
|
||||
@@ -342,9 +342,7 @@ class _HomeScreenState extends State<HomeScreen>
|
||||
if (showWaitingIndicator)
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: HomeWaitingIndicator(
|
||||
label: stageLabel(state.currentStage),
|
||||
),
|
||||
child: HomeWaitingIndicator(label: _agentWaitingLabel(state)),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
@@ -494,6 +492,13 @@ class _HomeScreenState extends State<HomeScreen>
|
||||
return state.isWaitingFirstToken || state.isStreaming || state.isCancelling;
|
||||
}
|
||||
|
||||
String _agentWaitingLabel(ChatState state) {
|
||||
if (state.isWaitingFirstToken && !state.hasSeenStep) {
|
||||
return context.l10n.agentStageRequesting;
|
||||
}
|
||||
return stageLabel(state.currentStage);
|
||||
}
|
||||
|
||||
void _handleScrollChanged() {
|
||||
if (!_scrollController.hasClients) {
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../core/theme/design_tokens.dart';
|
||||
|
||||
const homeBackgroundFieldKey = ValueKey('home_background_field');
|
||||
|
||||
class HomeBackgroundField extends StatelessWidget {
|
||||
@@ -13,12 +15,65 @@ class HomeBackgroundField extends StatelessWidget {
|
||||
key: homeBackgroundFieldKey,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [colorScheme.surface, colorScheme.surfaceContainerLowest],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
colorScheme.surface,
|
||||
colorScheme.surfaceContainerLow,
|
||||
colorScheme.surface,
|
||||
],
|
||||
stops: const [0, 0.38, 1],
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned(
|
||||
top: -(AppSpacing.xxl * 2),
|
||||
left: -(AppSpacing.xxl * 2),
|
||||
child: _AmbientOrb(
|
||||
color: colorScheme.primaryContainer.withValues(alpha: 0.55),
|
||||
size: AppSpacing.xxl * 8,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: -(AppSpacing.xxl * 2),
|
||||
top: AppSpacing.xxl,
|
||||
child: _AmbientOrb(
|
||||
color: colorScheme.secondaryContainer.withValues(alpha: 0.42),
|
||||
size: AppSpacing.xxl * 6,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AmbientOrb extends StatelessWidget {
|
||||
const _AmbientOrb({required this.color, required this.size});
|
||||
|
||||
final Color color;
|
||||
final double size;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IgnorePointer(
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: RadialGradient(
|
||||
colors: [
|
||||
color,
|
||||
color.withValues(alpha: 0.12),
|
||||
color.withValues(alpha: 0),
|
||||
],
|
||||
stops: const [0, 0.55, 1],
|
||||
),
|
||||
),
|
||||
),
|
||||
child: const SizedBox.expand(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
|
||||
import '../../../../core/l10n/l10n.dart';
|
||||
import '../../../../core/theme/design_tokens.dart';
|
||||
|
||||
const homeFloatingHeaderKey = ValueKey('home_floating_header');
|
||||
const homeFloatingHeaderTitleKey = ValueKey('home_floating_header_title');
|
||||
const _actionSlotWidth =
|
||||
(AppSpacing.xxl + AppSpacing.lg) * 2 + AppSpacing.sm + AppSpacing.sm;
|
||||
|
||||
class HomeFloatingHeader extends StatelessWidget {
|
||||
const HomeFloatingHeader({
|
||||
@@ -33,52 +36,66 @@ class HomeFloatingHeader extends StatelessWidget {
|
||||
AppSpacing.xs,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface.withValues(alpha: 0.95),
|
||||
border: Border(bottom: BorderSide(color: colorScheme.outlineVariant)),
|
||||
color: colorScheme.surface.withValues(alpha: 0.92),
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: colorScheme.outlineVariant.withValues(alpha: 0.65),
|
||||
),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: colorScheme.shadow.withValues(alpha: 0.04),
|
||||
blurRadius: AppSpacing.xl,
|
||||
offset: const Offset(AppSpacing.none, AppSpacing.xs),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_HeaderIconButton(
|
||||
SizedBox(
|
||||
width: _actionSlotWidth,
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: _HeaderIconButton(
|
||||
icon: LucideIcons.settings,
|
||||
onPressed: onTapSettings,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_HeaderIconButton(
|
||||
icon: LucideIcons.calendar,
|
||||
onPressed: onTapCalendar,
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
_MessagesButton(
|
||||
unreadCount: unreadCount,
|
||||
onPressed: onTapMessages,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IgnorePointer(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.xl * 3),
|
||||
child: Text(
|
||||
'Linksy',
|
||||
key: homeFloatingHeaderTitleKey,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: AppSpacing.lg + (AppSpacing.xs / 2),
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
context.l10n.appTitle,
|
||||
key: homeFloatingHeaderTitleKey,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: AppSpacing.lg,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 0.2,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: _actionSlotWidth,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_HeaderIconButton(
|
||||
icon: LucideIcons.calendar,
|
||||
onPressed: onTapCalendar,
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
_MessagesButton(
|
||||
unreadCount: unreadCount,
|
||||
onPressed: onTapMessages,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -103,7 +120,11 @@ class _HeaderIconButton extends StatelessWidget {
|
||||
minHeight: AppSpacing.xxl + AppSpacing.lg,
|
||||
),
|
||||
onPressed: onPressed,
|
||||
icon: Icon(icon, size: AppSpacing.xxl, color: colorScheme.onSurface),
|
||||
icon: Icon(
|
||||
icon,
|
||||
size: AppSpacing.xxl,
|
||||
color: colorScheme.onSurface.withValues(alpha: 0.95),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -145,7 +166,11 @@ class _MessagesButton extends StatelessWidget {
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.error,
|
||||
borderRadius: BorderRadius.circular(AppSpacing.sm),
|
||||
borderRadius: BorderRadius.circular(AppSpacing.md),
|
||||
border: Border.all(
|
||||
color: colorScheme.surface,
|
||||
width: AppSpacing.xs / 2,
|
||||
),
|
||||
),
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: AppSpacing.lg,
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
"homeStopRequested": "Stop requested",
|
||||
"homeNoValidSpeech": "No valid speech detected. Please move closer to the microphone and retry.",
|
||||
"agentStageRouting": "Analyzing intent",
|
||||
"agentStageRequesting": "Requesting server",
|
||||
"agentStageExecution": "Executing task",
|
||||
"agentStageMemory": "Loading memory",
|
||||
"agentStageProcessing": "Processing task",
|
||||
@@ -159,7 +160,14 @@
|
||||
}
|
||||
},
|
||||
"uiSchemaActionFallback": "Action",
|
||||
"uiSchemaStatusInfo": "Info",
|
||||
"uiSchemaStatusSuccess": "Completed",
|
||||
"uiSchemaStatusWarning": "Warning",
|
||||
"uiSchemaStatusError": "Failed",
|
||||
"uiSchemaStatusPending": "In progress",
|
||||
"uiSchemaActionNotImplemented": "This action is not available yet",
|
||||
"uiSchemaUrlInvalid": "Invalid URL",
|
||||
"uiSchemaUrlOpenFailed": "Unable to open URL",
|
||||
"uiSchemaNavigationInvalidParams": "Invalid navigation params",
|
||||
"uiSchemaNavigationInvalidPath": "Invalid navigation path",
|
||||
"notificationSnoozeMinutes": "{minutes} min",
|
||||
@@ -771,5 +779,12 @@
|
||||
"title": {}
|
||||
}
|
||||
},
|
||||
"messagesCalendarCardDeletedWithoutTitle": "Calendar event deleted"
|
||||
"messagesCalendarCardDeletedWithoutTitle": "Calendar event deleted",
|
||||
"calendarDetailSubscribers": "Subscribers ({count})",
|
||||
"@calendarDetailSubscribers": {
|
||||
"placeholders": {
|
||||
"count": {"type": "int"}
|
||||
}
|
||||
},
|
||||
"calendarOwnerBadge": "Owner"
|
||||
}
|
||||
|
||||
@@ -464,6 +464,12 @@ abstract class AppLocalizations {
|
||||
/// **'意图识别中'**
|
||||
String get agentStageRouting;
|
||||
|
||||
/// No description provided for @agentStageRequesting.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'网络请求中'**
|
||||
String get agentStageRequesting;
|
||||
|
||||
/// No description provided for @agentStageExecution.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
@@ -836,12 +842,54 @@ abstract class AppLocalizations {
|
||||
/// **'操作'**
|
||||
String get uiSchemaActionFallback;
|
||||
|
||||
/// No description provided for @uiSchemaStatusInfo.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'提示'**
|
||||
String get uiSchemaStatusInfo;
|
||||
|
||||
/// No description provided for @uiSchemaStatusSuccess.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'已完成'**
|
||||
String get uiSchemaStatusSuccess;
|
||||
|
||||
/// No description provided for @uiSchemaStatusWarning.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'提醒'**
|
||||
String get uiSchemaStatusWarning;
|
||||
|
||||
/// No description provided for @uiSchemaStatusError.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'失败'**
|
||||
String get uiSchemaStatusError;
|
||||
|
||||
/// No description provided for @uiSchemaStatusPending.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'进行中'**
|
||||
String get uiSchemaStatusPending;
|
||||
|
||||
/// No description provided for @uiSchemaActionNotImplemented.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'该操作暂未接入'**
|
||||
String get uiSchemaActionNotImplemented;
|
||||
|
||||
/// No description provided for @uiSchemaUrlInvalid.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'链接无效'**
|
||||
String get uiSchemaUrlInvalid;
|
||||
|
||||
/// No description provided for @uiSchemaUrlOpenFailed.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'无法打开链接'**
|
||||
String get uiSchemaUrlOpenFailed;
|
||||
|
||||
/// No description provided for @uiSchemaNavigationInvalidParams.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
@@ -3408,6 +3456,18 @@ abstract class AppLocalizations {
|
||||
/// In zh, this message translates to:
|
||||
/// **'日历事件已删除'**
|
||||
String get messagesCalendarCardDeletedWithoutTitle;
|
||||
|
||||
/// No description provided for @calendarDetailSubscribers.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'已订阅 ({count}人)'**
|
||||
String calendarDetailSubscribers(int count);
|
||||
|
||||
/// No description provided for @calendarOwnerBadge.
|
||||
///
|
||||
/// In zh, this message translates to:
|
||||
/// **'所有者'**
|
||||
String get calendarOwnerBadge;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate
|
||||
|
||||
@@ -209,6 +209,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get agentStageRouting => 'Analyzing intent';
|
||||
|
||||
@override
|
||||
String get agentStageRequesting => 'Requesting server';
|
||||
|
||||
@override
|
||||
String get agentStageExecution => 'Executing task';
|
||||
|
||||
@@ -411,9 +414,30 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get uiSchemaActionFallback => 'Action';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusInfo => 'Info';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusSuccess => 'Completed';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusWarning => 'Warning';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusError => 'Failed';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusPending => 'In progress';
|
||||
|
||||
@override
|
||||
String get uiSchemaActionNotImplemented => 'This action is not available yet';
|
||||
|
||||
@override
|
||||
String get uiSchemaUrlInvalid => 'Invalid URL';
|
||||
|
||||
@override
|
||||
String get uiSchemaUrlOpenFailed => 'Unable to open URL';
|
||||
|
||||
@override
|
||||
String get uiSchemaNavigationInvalidParams => 'Invalid navigation params';
|
||||
|
||||
@@ -1837,4 +1861,12 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get messagesCalendarCardDeletedWithoutTitle =>
|
||||
'Calendar event deleted';
|
||||
|
||||
@override
|
||||
String calendarDetailSubscribers(int count) {
|
||||
return 'Subscribers ($count)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get calendarOwnerBadge => 'Owner';
|
||||
}
|
||||
|
||||
@@ -198,6 +198,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get agentStageRouting => '意图识别中';
|
||||
|
||||
@override
|
||||
String get agentStageRequesting => '网络请求中';
|
||||
|
||||
@override
|
||||
String get agentStageExecution => '任务执行中';
|
||||
|
||||
@@ -397,9 +400,30 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get uiSchemaActionFallback => '操作';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusInfo => '提示';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusSuccess => '已完成';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusWarning => '提醒';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusError => '失败';
|
||||
|
||||
@override
|
||||
String get uiSchemaStatusPending => '进行中';
|
||||
|
||||
@override
|
||||
String get uiSchemaActionNotImplemented => '该操作暂未接入';
|
||||
|
||||
@override
|
||||
String get uiSchemaUrlInvalid => '链接无效';
|
||||
|
||||
@override
|
||||
String get uiSchemaUrlOpenFailed => '无法打开链接';
|
||||
|
||||
@override
|
||||
String get uiSchemaNavigationInvalidParams => '导航参数无效';
|
||||
|
||||
@@ -1790,4 +1814,12 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get messagesCalendarCardDeletedWithoutTitle => '日历事件已删除';
|
||||
|
||||
@override
|
||||
String calendarDetailSubscribers(int count) {
|
||||
return '已订阅 ($count人)';
|
||||
}
|
||||
|
||||
@override
|
||||
String get calendarOwnerBadge => '所有者';
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
"homeStopRequested": "已请求停止",
|
||||
"homeNoValidSpeech": "未识别到有效语音,请靠近麦克风并连续说话后重试",
|
||||
"agentStageRouting": "意图识别中",
|
||||
"agentStageRequesting": "网络请求中",
|
||||
"agentStageExecution": "任务执行中",
|
||||
"agentStageMemory": "记忆提取中",
|
||||
"agentStageProcessing": "任务处理中",
|
||||
@@ -159,7 +160,14 @@
|
||||
}
|
||||
},
|
||||
"uiSchemaActionFallback": "操作",
|
||||
"uiSchemaStatusInfo": "提示",
|
||||
"uiSchemaStatusSuccess": "已完成",
|
||||
"uiSchemaStatusWarning": "提醒",
|
||||
"uiSchemaStatusError": "失败",
|
||||
"uiSchemaStatusPending": "进行中",
|
||||
"uiSchemaActionNotImplemented": "该操作暂未接入",
|
||||
"uiSchemaUrlInvalid": "链接无效",
|
||||
"uiSchemaUrlOpenFailed": "无法打开链接",
|
||||
"uiSchemaNavigationInvalidParams": "导航参数无效",
|
||||
"uiSchemaNavigationInvalidPath": "导航路径无效",
|
||||
"notificationSnoozeMinutes": "{minutes} 分钟",
|
||||
@@ -771,5 +779,12 @@
|
||||
"title": {}
|
||||
}
|
||||
},
|
||||
"messagesCalendarCardDeletedWithoutTitle": "日历事件已删除"
|
||||
"messagesCalendarCardDeletedWithoutTitle": "日历事件已删除",
|
||||
"calendarDetailSubscribers": "已订阅 ({count}人)",
|
||||
"@calendarDetailSubscribers": {
|
||||
"placeholders": {
|
||||
"count": {"type": "int"}
|
||||
}
|
||||
},
|
||||
"calendarOwnerBadge": "所有者"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/theme/design_tokens.dart';
|
||||
|
||||
class AppInput extends StatelessWidget {
|
||||
final String label;
|
||||
final String hint;
|
||||
@@ -43,7 +45,20 @@ class AppInput extends StatelessWidget {
|
||||
keyboardType: keyboardType,
|
||||
maxLines: maxLines,
|
||||
enabled: enabled,
|
||||
decoration: InputDecoration(hintText: hint, suffixIcon: suffix),
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
suffixIcon: suffix,
|
||||
filled: true,
|
||||
fillColor: colorScheme.surfaceContainerLow,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.lg,
|
||||
vertical: AppSpacing.lg,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../data/models/dial_codes.dart';
|
||||
|
||||
class PhonePrefixSelector extends StatelessWidget {
|
||||
const PhonePrefixSelector({
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.items,
|
||||
List<DialCode>? items,
|
||||
this.onChanged,
|
||||
});
|
||||
}) : items = items ?? kDialCodes;
|
||||
|
||||
final String value;
|
||||
final List<String> items;
|
||||
final List<DialCode> items;
|
||||
final ValueChanged<String>? onChanged;
|
||||
|
||||
@override
|
||||
@@ -21,7 +23,10 @@ class PhonePrefixSelector extends StatelessWidget {
|
||||
onSelected: onChanged,
|
||||
itemBuilder: (context) => items
|
||||
.map(
|
||||
(item) => PopupMenuItem<String>(value: item, child: Text(item)),
|
||||
(item) => PopupMenuItem<String>(
|
||||
value: item.value,
|
||||
child: Text(item.value),
|
||||
),
|
||||
)
|
||||
.toList(growable: false),
|
||||
color: colorScheme.surface,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../core/l10n/l10n.dart';
|
||||
import '../../../core/theme/design_tokens.dart';
|
||||
import 'toast_type.dart';
|
||||
|
||||
class ToastTypeConfig {
|
||||
@@ -25,18 +26,22 @@ class ToastTypeConfig {
|
||||
|
||||
return switch (type) {
|
||||
ToastType.success => ToastTypeConfig(
|
||||
surfaceColor: colorScheme.tertiaryContainer,
|
||||
borderColor: colorScheme.tertiary,
|
||||
iconColor: colorScheme.tertiary,
|
||||
textColor: colorScheme.onTertiaryContainer,
|
||||
surfaceColor: colorScheme.primaryContainer,
|
||||
borderColor: colorScheme.primary,
|
||||
iconColor: colorScheme.primary,
|
||||
textColor: colorScheme.onPrimaryContainer,
|
||||
label: l10n.toastLabelSuccess,
|
||||
icon: Icons.check_circle_outline,
|
||||
),
|
||||
ToastType.warning => ToastTypeConfig(
|
||||
surfaceColor: colorScheme.secondaryContainer,
|
||||
borderColor: colorScheme.secondary,
|
||||
iconColor: colorScheme.secondary,
|
||||
textColor: colorScheme.onSecondaryContainer,
|
||||
surfaceColor: Theme.of(
|
||||
context,
|
||||
).extension<AppColorPalette>()!.warningContainer,
|
||||
borderColor: Theme.of(context).extension<AppColorPalette>()!.warning,
|
||||
iconColor: Theme.of(context).extension<AppColorPalette>()!.warning,
|
||||
textColor: Theme.of(
|
||||
context,
|
||||
).extension<AppColorPalette>()!.onWarningContainer,
|
||||
label: l10n.toastLabelWarning,
|
||||
icon: Icons.warning_amber_rounded,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user