refactor: new chat page text
This commit is contained in:
85
lib/core/utils/user_display_name.dart
Normal file
85
lib/core/utils/user_display_name.dart
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import '../models/user.dart' as models;
|
||||||
|
|
||||||
|
String deriveUserDisplayName(dynamic user, {String fallback = 'User'}) {
|
||||||
|
if (user == null) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalize(String? value) {
|
||||||
|
if (value == null) return '';
|
||||||
|
final trimmed = value.trim();
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
String emailFallback(String? email) {
|
||||||
|
final trimmed = normalize(email);
|
||||||
|
if (trimmed.isEmpty) return '';
|
||||||
|
final at = trimmed.indexOf('@');
|
||||||
|
if (at > 0) {
|
||||||
|
return trimmed.substring(0, at);
|
||||||
|
}
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user is models.User) {
|
||||||
|
final name = normalize(user.name);
|
||||||
|
if (name.isNotEmpty) return name;
|
||||||
|
|
||||||
|
final username = normalize(user.username);
|
||||||
|
if (username.isNotEmpty) return username;
|
||||||
|
|
||||||
|
final email = emailFallback(user.email);
|
||||||
|
if (email.isNotEmpty) return email;
|
||||||
|
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user is Map) {
|
||||||
|
String? pick(Map<dynamic, dynamic> source) {
|
||||||
|
for (final key in const [
|
||||||
|
'name',
|
||||||
|
'display_name',
|
||||||
|
'preferred_username',
|
||||||
|
'username',
|
||||||
|
]) {
|
||||||
|
final value = source[key];
|
||||||
|
final normalized = normalize(value is String ? value : null);
|
||||||
|
if (normalized.isNotEmpty) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final topLevel = pick(user);
|
||||||
|
if (topLevel != null && topLevel.isNotEmpty) {
|
||||||
|
return topLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
final nestedUser = user['user'];
|
||||||
|
if (nestedUser is Map) {
|
||||||
|
final nested = pick(nestedUser);
|
||||||
|
if (nested != null && nested.isNotEmpty) {
|
||||||
|
return nested;
|
||||||
|
}
|
||||||
|
final email = emailFallback(nestedUser['email'] as String?);
|
||||||
|
if (email.isNotEmpty) {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final email = emailFallback(user['email'] as String?);
|
||||||
|
if (email.isNotEmpty) {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
final asString = normalize(user.toString());
|
||||||
|
if (asString.isNotEmpty) {
|
||||||
|
return asString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
@@ -10,8 +10,10 @@ import 'package:flutter_animate/flutter_animate.dart';
|
|||||||
import 'dart:io' show Platform;
|
import 'dart:io' show Platform;
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import '../../../core/providers/app_providers.dart';
|
import '../../../core/providers/app_providers.dart';
|
||||||
|
import '../../../core/auth/auth_state_manager.dart';
|
||||||
import '../providers/chat_providers.dart';
|
import '../providers/chat_providers.dart';
|
||||||
import '../../../core/utils/debug_logger.dart';
|
import '../../../core/utils/debug_logger.dart';
|
||||||
|
import '../../../core/utils/user_display_name.dart';
|
||||||
|
|
||||||
import '../widgets/modern_chat_input.dart';
|
import '../widgets/modern_chat_input.dart';
|
||||||
import '../widgets/user_message_bubble.dart';
|
import '../widgets/user_message_bubble.dart';
|
||||||
@@ -847,6 +849,15 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEmptyState(ThemeData theme) {
|
Widget _buildEmptyState(ThemeData theme) {
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final currentUserAsync = ref.watch(currentUserProvider);
|
||||||
|
final userFromProfile = currentUserAsync.maybeWhen(
|
||||||
|
data: (user) => user,
|
||||||
|
orElse: () => null,
|
||||||
|
);
|
||||||
|
final dynamic authUser = ref.watch(authUserProvider);
|
||||||
|
final user = userFromProfile ?? authUser;
|
||||||
|
final greetingName = deriveUserDisplayName(user);
|
||||||
return Center(
|
return Center(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(Spacing.lg),
|
padding: const EdgeInsets.all(Spacing.lg),
|
||||||
@@ -886,7 +897,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
|||||||
const SizedBox(height: Spacing.xl),
|
const SizedBox(height: Spacing.xl),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
AppLocalizations.of(context)!.onboardStartTitle,
|
l10n.onboardStartTitle(greetingName),
|
||||||
style: theme.textTheme.headlineSmall?.copyWith(
|
style: theme.textTheme.headlineSmall?.copyWith(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: context.conduitTheme.textPrimary,
|
color: context.conduitTheme.textPrimary,
|
||||||
@@ -897,7 +908,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
|
|||||||
const SizedBox(height: Spacing.sm),
|
const SizedBox(height: Spacing.sm),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
AppLocalizations.of(context)!.typeBelowToBegin,
|
l10n.typeBelowToBegin,
|
||||||
style: theme.textTheme.bodyLarge?.copyWith(
|
style: theme.textTheme.bodyLarge?.copyWith(
|
||||||
color: context.conduitTheme.textSecondary,
|
color: context.conduitTheme.textSecondary,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import '../../../shared/utils/ui_utils.dart';
|
|||||||
import '../../../shared/widgets/themed_dialogs.dart';
|
import '../../../shared/widgets/themed_dialogs.dart';
|
||||||
import '../../../core/auth/auth_state_manager.dart';
|
import '../../../core/auth/auth_state_manager.dart';
|
||||||
import 'package:conduit/l10n/app_localizations.dart';
|
import 'package:conduit/l10n/app_localizations.dart';
|
||||||
import '../../../core/models/user.dart' as models;
|
import '../../../core/utils/user_display_name.dart';
|
||||||
|
|
||||||
class ChatsDrawer extends ConsumerStatefulWidget {
|
class ChatsDrawer extends ConsumerStatefulWidget {
|
||||||
const ChatsDrawer({super.key});
|
const ChatsDrawer({super.key});
|
||||||
@@ -1148,43 +1148,6 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
);
|
);
|
||||||
final dynamic authUser = ref.watch(authUserProvider);
|
final dynamic authUser = ref.watch(authUserProvider);
|
||||||
final user = userFromProfile ?? authUser;
|
final user = userFromProfile ?? authUser;
|
||||||
String _displayName(dynamic u) {
|
|
||||||
if (u == null) return 'User';
|
|
||||||
if (u is models.User) {
|
|
||||||
return (u.name?.isNotEmpty == true ? u.name : u.username) ?? 'User';
|
|
||||||
}
|
|
||||||
if (u is Map) {
|
|
||||||
final Map m = u;
|
|
||||||
String? _asString(dynamic v) =>
|
|
||||||
v is String && v.trim().isNotEmpty ? v.trim() : null;
|
|
||||||
String? _pick(Map source) {
|
|
||||||
return _asString(source['name']) ??
|
|
||||||
_asString(source['display_name']) ??
|
|
||||||
_asString(source['preferred_username']) ??
|
|
||||||
_asString(source['username']);
|
|
||||||
}
|
|
||||||
|
|
||||||
final top = _pick(m);
|
|
||||||
if (top != null) return top;
|
|
||||||
final nestedUser = m['user'];
|
|
||||||
if (nestedUser is Map) {
|
|
||||||
final nested = _pick(nestedUser);
|
|
||||||
if (nested != null) return nested;
|
|
||||||
final nestedEmail = _asString(nestedUser['email']);
|
|
||||||
if (nestedEmail != null && nestedEmail.contains('@')) {
|
|
||||||
return nestedEmail.split('@').first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final email = _asString(m['email']);
|
|
||||||
if (email != null && email.contains('@')) {
|
|
||||||
return email.split('@').first;
|
|
||||||
}
|
|
||||||
return 'User';
|
|
||||||
}
|
|
||||||
// Fallback to string representation if some other type
|
|
||||||
final s = u.toString();
|
|
||||||
return s.isNotEmpty ? s : 'User';
|
|
||||||
}
|
|
||||||
|
|
||||||
String _initial(String name) {
|
String _initial(String name) {
|
||||||
if (name.isEmpty) return 'U';
|
if (name.isEmpty) return 'U';
|
||||||
@@ -1192,7 +1155,7 @@ class _ChatsDrawerState extends ConsumerState<ChatsDrawer> {
|
|||||||
return ch.toUpperCase();
|
return ch.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
final displayName = _displayName(user);
|
final displayName = deriveUserDisplayName(user);
|
||||||
final initial = _initial(displayName);
|
final initial = _initial(displayName);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(Spacing.sm, 0, Spacing.sm, Spacing.sm),
|
padding: const EdgeInsets.fromLTRB(Spacing.sm, 0, Spacing.sm, Spacing.sm),
|
||||||
|
|||||||
@@ -1,29 +1,44 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import '../../../shared/theme/theme_extensions.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import '../../../shared/widgets/sheet_handle.dart';
|
|
||||||
import 'package:conduit/l10n/app_localizations.dart';
|
import 'package:conduit/l10n/app_localizations.dart';
|
||||||
|
|
||||||
class OnboardingSheet extends StatefulWidget {
|
import '../../../core/auth/auth_state_manager.dart';
|
||||||
|
import '../../../core/providers/app_providers.dart';
|
||||||
|
import '../../../core/utils/user_display_name.dart';
|
||||||
|
import '../../../shared/theme/theme_extensions.dart';
|
||||||
|
import '../../../shared/widgets/sheet_handle.dart';
|
||||||
|
|
||||||
|
class OnboardingSheet extends ConsumerStatefulWidget {
|
||||||
const OnboardingSheet({super.key});
|
const OnboardingSheet({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<OnboardingSheet> createState() => _OnboardingSheetState();
|
ConsumerState<OnboardingSheet> createState() => _OnboardingSheetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OnboardingSheetState extends State<OnboardingSheet> {
|
class _OnboardingSheetState extends ConsumerState<OnboardingSheet> {
|
||||||
final PageController _controller = PageController();
|
final PageController _controller = PageController();
|
||||||
int _index = 0;
|
int _index = 0;
|
||||||
late List<_OnboardingPage> _pages;
|
|
||||||
|
|
||||||
@override
|
void _next(int pageCount) {
|
||||||
void didChangeDependencies() {
|
if (_index < pageCount - 1) {
|
||||||
super.didChangeDependencies();
|
_controller.nextPage(
|
||||||
final l10n = AppLocalizations.of(context)!;
|
duration: AnimationDuration.fast,
|
||||||
_pages = [
|
curve: AnimationCurves.easeInOut,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<_OnboardingPage> _buildPages(
|
||||||
|
AppLocalizations l10n,
|
||||||
|
String greetingName,
|
||||||
|
) {
|
||||||
|
return [
|
||||||
_OnboardingPage(
|
_OnboardingPage(
|
||||||
title: l10n.onboardStartTitle,
|
title: l10n.onboardStartTitle(greetingName),
|
||||||
subtitle: l10n.onboardStartSubtitle,
|
subtitle: l10n.onboardStartSubtitle,
|
||||||
icon: CupertinoIcons.chat_bubble_2,
|
icon: CupertinoIcons.chat_bubble_2,
|
||||||
bullets: [l10n.onboardStartBullet1, l10n.onboardStartBullet2],
|
bullets: [l10n.onboardStartBullet1, l10n.onboardStartBullet2],
|
||||||
@@ -49,20 +64,20 @@ class _OnboardingSheetState extends State<OnboardingSheet> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
void _next() {
|
|
||||||
if (_index < _pages.length - 1) {
|
|
||||||
_controller.nextPage(
|
|
||||||
duration: AnimationDuration.fast,
|
|
||||||
curve: AnimationCurves.easeInOut,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
Navigator.pop(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final height = MediaQuery.of(context).size.height;
|
final height = MediaQuery.of(context).size.height;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final currentUserAsync = ref.watch(currentUserProvider);
|
||||||
|
final userFromProfile = currentUserAsync.maybeWhen(
|
||||||
|
data: (user) => user,
|
||||||
|
orElse: () => null,
|
||||||
|
);
|
||||||
|
final dynamic authUser = ref.watch(authUserProvider);
|
||||||
|
final user = userFromProfile ?? authUser;
|
||||||
|
final greetingName = deriveUserDisplayName(user);
|
||||||
|
final pages = _buildPages(l10n, greetingName);
|
||||||
|
final pageCount = pages.length;
|
||||||
return Container(
|
return Container(
|
||||||
height: height * 0.7,
|
height: height * 0.7,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -83,10 +98,10 @@ class _OnboardingSheetState extends State<OnboardingSheet> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
itemCount: _pages.length,
|
itemCount: pageCount,
|
||||||
onPageChanged: (i) => setState(() => _index = i),
|
onPageChanged: (i) => setState(() => _index = i),
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
final page = _pages[i];
|
final page = pages[i];
|
||||||
final content = _IllustratedPage(page: page);
|
final content = _IllustratedPage(page: page);
|
||||||
// Ensure content can scroll vertically when space is tight,
|
// Ensure content can scroll vertically when space is tight,
|
||||||
// while keeping it centered when there is enough space.
|
// while keeping it centered when there is enough space.
|
||||||
@@ -111,7 +126,7 @@ class _OnboardingSheetState extends State<OnboardingSheet> {
|
|||||||
const SizedBox(height: Spacing.md),
|
const SizedBox(height: Spacing.md),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: List.generate(_pages.length, (i) {
|
children: List.generate(pageCount, (i) {
|
||||||
final active = i == _index;
|
final active = i == _index;
|
||||||
return AnimatedContainer(
|
return AnimatedContainer(
|
||||||
duration: AnimationDuration.fast,
|
duration: AnimationDuration.fast,
|
||||||
@@ -136,7 +151,7 @@ class _OnboardingSheetState extends State<OnboardingSheet> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
AppLocalizations.of(context)!.skip,
|
l10n.skip,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: context.conduitTheme.textSecondary,
|
color: context.conduitTheme.textSecondary,
|
||||||
),
|
),
|
||||||
@@ -144,7 +159,7 @@ class _OnboardingSheetState extends State<OnboardingSheet> {
|
|||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: _next,
|
onPressed: () => _next(pageCount),
|
||||||
style: FilledButton.styleFrom(
|
style: FilledButton.styleFrom(
|
||||||
backgroundColor: context.conduitTheme.buttonPrimary,
|
backgroundColor: context.conduitTheme.buttonPrimary,
|
||||||
foregroundColor: context.conduitTheme.buttonPrimaryText,
|
foregroundColor: context.conduitTheme.buttonPrimaryText,
|
||||||
@@ -159,9 +174,7 @@ class _OnboardingSheetState extends State<OnboardingSheet> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
_index == _pages.length - 1
|
_index == pageCount - 1 ? l10n.done : l10n.next,
|
||||||
? AppLocalizations.of(context)!.done
|
|
||||||
: AppLocalizations.of(context)!.next,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
"skip": "Überspringen",
|
"skip": "Überspringen",
|
||||||
"next": "Weiter",
|
"next": "Weiter",
|
||||||
"done": "Fertig",
|
"done": "Fertig",
|
||||||
"onboardStartTitle": "Unterhaltung starten",
|
"onboardStartTitle": "Hallo, {username}",
|
||||||
"onboardStartSubtitle": "Wähle ein Modell und tippe los. Tippe jederzeit auf Neuer Chat.",
|
"onboardStartSubtitle": "Wähle ein Modell und tippe los. Tippe jederzeit auf Neuer Chat.",
|
||||||
"onboardStartBullet1": "Modellname oben antippen, um zu wechseln",
|
"onboardStartBullet1": "Modellname oben antippen, um zu wechseln",
|
||||||
"onboardStartBullet2": "Mit Neuer Chat den Kontext zurücksetzen",
|
"onboardStartBullet2": "Mit Neuer Chat den Kontext zurücksetzen",
|
||||||
|
|||||||
@@ -202,8 +202,8 @@
|
|||||||
"@next": {"description": "Onboarding: go to the next step."},
|
"@next": {"description": "Onboarding: go to the next step."},
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"@done": {"description": "Onboarding: finish the flow."},
|
"@done": {"description": "Onboarding: finish the flow."},
|
||||||
"onboardStartTitle": "Start a conversation",
|
"onboardStartTitle": "Hello, {username}",
|
||||||
"@onboardStartTitle": {"description": "Onboarding card: start chatting title."},
|
"@onboardStartTitle": {"description": "Onboarding card: start chatting title.", "placeholders": {"username": {"type": "String", "example": "Alex"}}},
|
||||||
"onboardStartSubtitle": "Choose a model, then type below to begin. Tap New Chat anytime.",
|
"onboardStartSubtitle": "Choose a model, then type below to begin. Tap New Chat anytime.",
|
||||||
"@onboardStartSubtitle": {"description": "Onboarding card: brief guidance to begin a chat."},
|
"@onboardStartSubtitle": {"description": "Onboarding card: brief guidance to begin a chat."},
|
||||||
"onboardStartBullet1": "Tap the model name in the top bar to switch models",
|
"onboardStartBullet1": "Tap the model name in the top bar to switch models",
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
"skip": "Ignorer",
|
"skip": "Ignorer",
|
||||||
"next": "Suivant",
|
"next": "Suivant",
|
||||||
"done": "Terminé",
|
"done": "Terminé",
|
||||||
"onboardStartTitle": "Commencer une conversation",
|
"onboardStartTitle": "Bonjour, {username}",
|
||||||
"onboardStartSubtitle": "Choisissez un modèle puis commencez à écrire. Touchez Nouveau chat à tout moment.",
|
"onboardStartSubtitle": "Choisissez un modèle puis commencez à écrire. Touchez Nouveau chat à tout moment.",
|
||||||
"onboardStartBullet1": "Touchez le nom du modèle en haut pour changer",
|
"onboardStartBullet1": "Touchez le nom du modèle en haut pour changer",
|
||||||
"onboardStartBullet2": "Utilisez Nouveau chat pour réinitialiser le contexte",
|
"onboardStartBullet2": "Utilisez Nouveau chat pour réinitialiser le contexte",
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
"skip": "Salta",
|
"skip": "Salta",
|
||||||
"next": "Avanti",
|
"next": "Avanti",
|
||||||
"done": "Fatto",
|
"done": "Fatto",
|
||||||
"onboardStartTitle": "Inizia una conversazione",
|
"onboardStartTitle": "Ciao, {username}",
|
||||||
"onboardStartSubtitle": "Scegli un modello e inizia a scrivere. Tocca Nuova chat in qualsiasi momento.",
|
"onboardStartSubtitle": "Scegli un modello e inizia a scrivere. Tocca Nuova chat in qualsiasi momento.",
|
||||||
"onboardStartBullet1": "Tocca il nome del modello in alto per cambiare",
|
"onboardStartBullet1": "Tocca il nome del modello in alto per cambiare",
|
||||||
"onboardStartBullet2": "Usa Nuova chat per azzerare il contesto",
|
"onboardStartBullet2": "Usa Nuova chat per azzerare il contesto",
|
||||||
|
|||||||
@@ -651,8 +651,8 @@ abstract class AppLocalizations {
|
|||||||
/// Onboarding card: start chatting title.
|
/// Onboarding card: start chatting title.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Start a conversation'**
|
/// **'Hello, {username}'**
|
||||||
String get onboardStartTitle;
|
String onboardStartTitle(String username);
|
||||||
|
|
||||||
/// Onboarding card: brief guidance to begin a chat.
|
/// Onboarding card: brief guidance to begin a chat.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -314,7 +314,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
String get done => 'Fertig';
|
String get done => 'Fertig';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartTitle => 'Unterhaltung starten';
|
String onboardStartTitle(String username) {
|
||||||
|
return 'Hallo, $username';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartSubtitle =>
|
String get onboardStartSubtitle =>
|
||||||
|
|||||||
@@ -310,7 +310,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
String get done => 'Done';
|
String get done => 'Done';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartTitle => 'Start a conversation';
|
String onboardStartTitle(String username) {
|
||||||
|
return 'Hello, $username';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartSubtitle =>
|
String get onboardStartSubtitle =>
|
||||||
|
|||||||
@@ -315,7 +315,9 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
String get done => 'Terminé';
|
String get done => 'Terminé';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartTitle => 'Commencer une conversation';
|
String onboardStartTitle(String username) {
|
||||||
|
return 'Bonjour, $username';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartSubtitle =>
|
String get onboardStartSubtitle =>
|
||||||
|
|||||||
@@ -310,7 +310,9 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
String get done => 'Fatto';
|
String get done => 'Fatto';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartTitle => 'Inizia una conversazione';
|
String onboardStartTitle(String username) {
|
||||||
|
return 'Ciao, $username';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onboardStartSubtitle =>
|
String get onboardStartSubtitle =>
|
||||||
|
|||||||
Reference in New Issue
Block a user