Compare commits

...

5 Commits

Author SHA1 Message Date
Inex Code 2fc20f43c3 fix(ui): New app bar now properly supports long titles 2022-10-06 10:38:29 +03:00
Inex Code 8aaf62ca5c Translated using Weblate (Russian)
Currently translated at 100.0% (351 of 351 strings)

Translation: SelfPrivacy/SelfPrivacy App
Translate-URL: http://weblate.selfprivacy.org/projects/selfprivacy/selfprivacy-app/ru/
2022-10-04 11:45:34 +00:00
Inex Code 53e8ae5ce8 Translated using Weblate (English)
Currently translated at 100.0% (351 of 351 strings)

Translation: SelfPrivacy/SelfPrivacy App
Translate-URL: http://weblate.selfprivacy.org/projects/selfprivacy/selfprivacy-app/en/
2022-10-04 11:45:34 +00:00
Inex Code 408b359a2a Merge pull request 'feat: MD3 app bars' (#126) from fix/better-app-bars into master
Reviewed-on: kherel/selfprivacy.org.app#126
2022-10-04 13:36:54 +03:00
Inex Code 129eb76a04 feat: MD3 app bars
Fixed #123 spent @2h
2022-10-04 13:36:37 +03:00
12 changed files with 1104 additions and 997 deletions

View File

@ -19,9 +19,9 @@
"close": "Close",
"connect": "Connect",
"domain": "Domain",
"saving": "Saving..",
"saving": "Saving",
"nickname": "Nickname",
"loading": "Loading...",
"loading": "Loading",
"later": "Skip to setup later",
"connect_to_existing": "Connect to an existing server",
"reset": "Reset",
@ -38,13 +38,13 @@
"about_project": "About us",
"about_application": "About",
"onboarding": "Onboarding",
"create_ssh_key": "Create SSH key",
"create_ssh_key": "Superuser SSH keys",
"console": "Console",
"application_settings": "Application settings"
},
"console_page": {
"title": "Console",
"waiting": "Waiting for initialization..."
"waiting": "Waiting for initialization"
},
"about_us_page": {
"title": "About us"
@ -61,7 +61,7 @@
"reset_config_title": "Reset application config",
"reset_config_description": "Reset api keys and root user",
"delete_server_title": "Delete server",
"delete_server_description": "This removes your server. It will be no longer accessible"
"delete_server_description": "This removes your server. It will be no longer accessible."
},
"ssh": {
"title": "SSH keys",
@ -79,7 +79,7 @@
"page1_title": "Digital independence, available to all of us",
"page1_text": "Mail, VPN, Messenger, social network and much more on your private server, under your control.",
"page2_title": "SelfPrivacy — it's not a cloud, but your personal datacenter",
"page2_text": "SelfPrivacy works only with your provider accounts: Hetzner, Cloudflare, Backblaze. If you do not own those, we'll help you to create them"
"page2_text": "SelfPrivacy works only with your provider accounts: Hetzner, Cloudflare, Backblaze. If you do not own those, we'll help you to create them."
},
"resource_chart": {
"month": "Month",
@ -133,7 +133,7 @@
"ok": "Records are OK",
"error": "Problems found",
"error_subtitle": "Tap here to fix them",
"refreshing": "Refreshing status...",
"refreshing": "Refreshing status",
"uninitialized": "Data is not retrieved yet",
"services_title": "Services",
"services_subtitle": "Type “A” records required for each service.",
@ -177,7 +177,7 @@
"data_migration_title": "Data migration",
"data_migration_notice": "During migration all services will be turned off.",
"start_migration_button": "Start migration",
"migration_process": "Migrating...",
"migration_process": "Migrating",
"migration_done": "Finish"
},
"not_ready_card": {
@ -276,9 +276,9 @@
"final": "Final step",
"create_server": "Create server",
"what": "What does it mean?",
"server_rebooted": "Server rebooted. Waiting for the last verification...",
"server_started": "Server started. It will be validated and rebooted now...",
"server_created": "Server created. DNS checks and server boot in progress...",
"server_rebooted": "Server rebooted. Waiting for the last verification",
"server_started": "Server started. It will be validated and rebooted now",
"server_created": "Server created. DNS checks and server boot in progress",
"until_the_next_check": "Until the next check: ",
"check": "Check",
"one_more_restart": "One more restart to apply your security certificates.",
@ -311,7 +311,7 @@
"hetzner_connected_description": "Communication established. Enter Hetzner token with access to {}:",
"hetzner_connected_placeholder": "Hetzner token",
"confirm_server": "Confirm server",
"confirm_server_description": "Found your server! Confirm it is correct.",
"confirm_server_description": "Found your server! Confirm it is the right one:",
"confirm_server_accept": "Yes! That's it",
"confirm_server_decline": "Choose a different server",
"choose_server": "Choose your server",
@ -356,7 +356,7 @@
},
"recovery_key": {
"key_connection_error": "Couldn't connect to the server.",
"key_synchronizing": "Synchronizing...",
"key_synchronizing": "Synchronizing",
"key_main_header": "Recovery key",
"key_main_description": "Is needed for SelfPrivacy authorization when all your other authorized devices aren't available.",
"key_amount_toggle": "Limit by number of uses",

View File

@ -21,7 +21,7 @@
"domain": "Домен",
"saving": "Сохранение…",
"nickname": "Никнейм",
"loading": "Загрузка",
"loading": "Загрузка",
"later": "Пропустить и настроить потом",
"connect_to_existing": "Подключиться к существующему серверу",
"reset": "Сбросить",
@ -29,22 +29,22 @@
"no_data": "Нет данных",
"wait": "Загрузка",
"remove": "Удалить",
"apply": "Подать",
"apply": "Применить",
"done": "Готово",
"continue": "Продолжить"
},
"more_page": {
"configuration_wizard": "Мастер Подключения",
"configuration_wizard": "Мастер настройки",
"about_project": "О проекте SelfPrivacy",
"about_application": "О приложении",
"onboarding": "Приветствие",
"console": "Консоль",
"create_ssh_key": "Создать ssh ключ",
"create_ssh_key": "SSH ключи администратора",
"application_settings": "Настройки приложения"
},
"console_page": {
"title": "Консоль",
"waiting": "Ждём инициализации..."
"waiting": "Ждём инициализации"
},
"about_us_page": {
"title": "О проекте SelfPrivacy"
@ -57,17 +57,17 @@
"application_settings": {
"title": "Настройки приложения",
"dark_theme_title": "Тёмная тема",
"dark_theme_description": "Сменить цветовую тему.",
"dark_theme_description": "Сменить цветовую тему",
"reset_config_title": "Сброс настроек",
"reset_config_description": "Сбросить API ключи а также root пользвателя.",
"reset_config_description": "Сбросить API ключи, а также root пользователя",
"delete_server_title": "Удалить сервер",
"delete_server_description": "Действие приведет к удалению сервера. После этого он будет недоступен."
"delete_server_description": "Действие приведёт к удалению сервера. После этого он будет недоступен."
},
"ssh": {
"title": "SSH ключи",
"create": "Добавить SSH ключ",
"delete": "Удалить SSH ключ",
"delete_confirm_question": "Вы уверены что хотите удалить следующий ключ?",
"delete_confirm_question": "Вы уверены, что хотите удалить следующий ключ?",
"subtitle_with_keys": "Ключей: {}",
"subtitle_without_keys": "Ключей нет",
"no_key_name": "Безымянный ключ",
@ -92,11 +92,11 @@
},
"server": {
"card_title": "Сервер",
"description": "Это виртуальный компьютер на котором работают все Ваши сервисы.",
"description": "Это виртуальный компьютер на котором работают все ваши сервисы",
"general_information": "Общая информация",
"resource_usage": "Потребление ресурсов",
"allow_autoupgrade": "Разрешить авто-обноления",
"allow_autoupgrade_hint": "Разрешить автоматичесую установку обновлений на сервер",
"allow_autoupgrade": "Разрешить авто-обновления",
"allow_autoupgrade_hint": "Разрешить автоматическую установку обновлений на сервер",
"reboot_after_upgrade": "Перезагружать после обновлений",
"reboot_after_upgrade_hint": "Автоматически перезагружать сервер после применения обновлений",
"server_timezone": "Часовой пояс сервера",
@ -136,7 +136,7 @@
"ok": "Записи в норме",
"error": "Обнаружены проблемы",
"error_subtitle": "Нажмите здесь, чтобы исправить",
"refreshing": "Обновление данных...",
"refreshing": "Обновление данных",
"uninitialized": "Данные ещё не получены",
"services_title": "Сервисы",
"services_subtitle": "Записи типа “A” необходимые для работы сервисов.",
@ -155,7 +155,7 @@
"create_new": "Создать новую копию",
"creating": "Создание копии: {}%",
"restoring": "Восстановление из копии",
"error_pending": "Сервер вернул ошибку: проверьте её ниже.",
"error_pending": "Сервер вернул ошибку: проверьте её ниже",
"restore_alert": "Вы собираетесь восстановить из копии созданной {}. Все текущие данные будут потеряны. Вы уверены?",
"refresh": "Обновить статус",
"refetch_backups": "Обновить список копий",
@ -180,7 +180,7 @@
"data_migration_title": "Миграция данных",
"data_migration_notice": "На время миграции данных все сервисы будут выключены.",
"start_migration_button": "Начать миграцию",
"migration_process": "Мигрируем...",
"migration_process": "Мигрируем",
"migration_done": "Завершить"
},
"not_ready_card": {
@ -195,7 +195,16 @@
"disable": "Выключить сервис",
"enable": "Включить сервис",
"move": "Переместить на другой диск",
"uses": "Использует {usage} на {volume}"
"uses": "Использует {usage} на {volume}",
"status": {
"active": "Включено и работает",
"inactive": "Остановлено",
"failed": "Не удалось запустить",
"off": "Отключено",
"activating": "Включается",
"deactivating": "Выключается",
"reloading": "Перезапускается"
}
},
"mail": {
"title": "Почта",
@ -232,13 +241,13 @@
"subtitle": "Закрытый VPN сервер"
},
"users": {
"add_new_user": "Добавьте первого пользователя.",
"add_new_user": "Добавьте первого пользователя",
"new_user": "Новый пользователь",
"delete_user": "Удалить пользователя",
"not_ready": "Подключите сервер, домен и DNS в разделе Провайдеры чтобы добавить первого пользователя",
"nobody_here": "Здесь будут отображаться пользователи.",
"nobody_here": "Здесь будут отображаться пользователи",
"login": "Логин",
"new_user_info_note": "Новый пользователь автоматически получит доступ ко всем сервисам.",
"new_user_info_note": "Новый пользователь автоматически получит доступ ко всем сервисам",
"delete_confirm_question": "Вы действительно хотите удалить учетную запись?",
"reset_password": "Сбросить пароль",
"account": "Учетная запись",
@ -254,14 +263,14 @@
},
"initializing": {
"connect_to_server": "Подключите сервер",
"place_where_data": "Здесь будут жить наши данные и SelfPrivacy-сервисы",
"place_where_data": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:",
"how": "Как получить API Token",
"hetzner_bad_key_error": "Hetzner API ключ неверен",
"cloudflare_bad_key_error": "Cloudflare API ключ неверен",
"backblaze_bad_key_error": "Информация о Backblaze хранилище неверна",
"connect_cloudflare": "Подключите CloudFlare",
"manage_domain_dns": "Для управления DNS вашего домена",
"cloudflare_api_token": "CloudFlare API Token",
"cloudflare_api_token": "CloudFlare API ключ",
"connect_backblaze_storage": "Подключите облачное хранилище Backblaze",
"no_connected_domains": "На данный момент подлюченных доменов нет",
"loading_domain_list": "Загружаем список доменов",
@ -270,15 +279,15 @@
"final": "Последний шаг",
"create_server": "Создать сервер",
"what": "Что это значит?",
"server_rebooted": "Сервер презагружен, ждем последнюю проверку.",
"server_started": "Cервер запущен, сейчас он будет проверен и перезагружен.",
"server_created": "Cервер создан, идет проверка ДНС адресов и запуск сервера.",
"server_rebooted": "Сервер перезагружен, ждём последнюю проверку…",
"server_started": "Сервер запущен. Сейчас он будет проверен и перезагружен…",
"server_created": "Сервер создан. Идёт проверка DNS адресов и запуск сервера…",
"until_the_next_check": "До следующей проверки: ",
"check": "Проверка",
"one_more_restart": "Сейчас будет дополнительная перезагрузка для активации сертификатов безопастности",
"one_more_restart": "Сейчас будет дополнительная перезагрузка для активации сертификатов безопасности.",
"create_master_account": "Создайте главную учетную запись",
"enter_nickname_and_password": "Введите никнейм и сложный пароль",
"finish": "Всё инициализировано.",
"finish": "Всё инициализировано",
"checks": "Проверок выполнено: \n{} / {}"
},
"recovering": {
@ -321,7 +330,8 @@
"confirm_cloudflare": "Подключение к Cloudflare",
"confirm_cloudflare_description": "Введите токен Cloudflare, который имеет права на {}:",
"confirm_backblze": "Подключение к Backblaze",
"confirm_backblaze_description": "Введите токен Backblaze, который имеет права на хранилище резервных копий:"
"confirm_backblaze_description": "Введите токен Backblaze, который имеет права на хранилище резервных копий:",
"confirm_backblaze": "Подключение к Backblaze"
},
"devices": {
"main_screen": {
@ -349,8 +359,8 @@
}
},
"recovery_key": {
"key_connection_error": "Не удалось соединиться с сервером",
"key_synchronizing": "Синхронизация...",
"key_connection_error": "Не удалось соединиться с сервером.",
"key_synchronizing": "Синхронизация",
"key_main_header": "Ключ восстановления",
"key_main_description": "Требуется для авторизации SelfPrivacy, когда авторизованные устройства недоступны.",
"key_amount_toggle": "Ограничить использования",
@ -376,7 +386,7 @@
"try_again": "Попробовать ещё раз?",
"are_you_sure": "Вы уверены?",
"purge_all_keys": "Стереть все ключи авторизации?",
"purge_all_keys_confirm": "Да, стереть все ключи!",
"purge_all_keys_confirm": "Да, стереть все ключи",
"delete_server_volume": "Удалить сервер и хранилище?",
"reboot": "Перезагрузить",
"you_cant_use_this_api": "Нельзя использовать этот API для доменом с подобным TLD.",
@ -389,7 +399,7 @@
"jobs": {
"title": "Задачи",
"start": "Начать выполенение",
"empty": "Пусто.",
"empty": "Задач нет",
"create_user": "Создать пользователя",
"delete_user": "Удалить пользователя",
"service_turn_off": "Остановить",
@ -397,7 +407,7 @@
"job_added": "Задача добавленна",
"run_jobs": "Запустите задачи",
"reboot_success": "Сервер перезагружается",
"reboot_failed": "Не удалось перезагрузить сервер, проверьте логи",
"reboot_failed": "Не удалось перезагрузить сервер, проверьте логи.",
"config_pull_failed": "Не удалось обновить конфигурацию сервера. Обновление ПО запущено.",
"upgrade_success": "Запущено обновление сервера",
"upgrade_failed": "Обновить сервер не вышло",

View File

@ -66,11 +66,6 @@ abstract class AppThemeFactory {
typography: appTypography,
useMaterial3: true,
scaffoldBackgroundColor: colorScheme.background,
appBarTheme: AppBarTheme(
elevation: 0,
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
),
);
return materialThemeData;

View File

@ -1,6 +1,4 @@
import 'package:flutter/material.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
class BrandHeader extends StatelessWidget {
const BrandHeader({
@ -15,25 +13,17 @@ class BrandHeader extends StatelessWidget {
final VoidCallback? onBackButtonPressed;
@override
Widget build(final BuildContext context) => Container(
height: 52,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(
left: hasBackButton ? 1 : 15,
Widget build(final BuildContext context) => AppBar(
title: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Text(title),
),
child: Row(
children: [
if (hasBackButton) ...[
IconButton(
icon: const Icon(BrandIcons.arrowLeft),
leading: hasBackButton
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed:
onBackButtonPressed ?? () => Navigator.of(context).pop(),
),
const SizedBox(width: 10),
],
BrandText.h4(title),
const Spacer(),
],
),
)
: null,
);
}

View File

@ -1,72 +1,145 @@
import 'package:flutter/material.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/pre_styled_buttons/flash_fab.dart';
import 'package:selfprivacy/ui/helpers/widget_size.dart';
class BrandHeroScreen extends StatelessWidget {
const BrandHeroScreen({
required this.children,
final super.key,
this.headerTitle = '',
this.hasBackButton = true,
this.hasFlashButton = true,
this.heroIcon,
this.heroTitle,
this.heroIconWidget,
this.heroTitle = '',
this.heroSubtitle,
this.onBackButtonPressed,
});
final List<Widget> children;
final String headerTitle;
final bool hasBackButton;
final bool hasFlashButton;
final IconData? heroIcon;
final String? heroTitle;
final Widget? heroIconWidget;
final String heroTitle;
final String? heroSubtitle;
final VoidCallback? onBackButtonPressed;
@override
Widget build(final BuildContext context) => SafeArea(
child: Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(52.0),
child: BrandHeader(
title: headerTitle,
Widget build(final BuildContext context) {
final Widget heroIconWidget = this.heroIconWidget ??
Icon(
heroIcon ?? Icons.help,
size: 48.0,
color: Theme.of(context).colorScheme.onBackground,
);
final bool hasHeroIcon = heroIcon != null || this.heroIconWidget != null;
return Scaffold(
floatingActionButton: hasFlashButton ? const BrandFab() : null,
body: CustomScrollView(
slivers: [
HeroSliverAppBar(
heroTitle: heroTitle,
hasHeroIcon: hasHeroIcon,
hasBackButton: hasBackButton,
onBackButtonPressed: onBackButtonPressed,
heroIconWidget: heroIconWidget,
),
),
floatingActionButton: hasFlashButton ? const BrandFab() : null,
body: ListView(
padding: const EdgeInsets.all(16.0),
children: <Widget>[
if (heroIcon != null)
Container(
alignment: Alignment.bottomLeft,
child: Icon(
heroIcon,
size: 48.0,
),
),
const SizedBox(height: 8.0),
if (heroTitle != null)
Text(
heroTitle!,
style: Theme.of(context).textTheme.headlineMedium!.copyWith(
color: Theme.of(context).colorScheme.onBackground,
),
textAlign: TextAlign.start,
),
const SizedBox(height: 8.0),
if (heroSubtitle != null)
SliverPadding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 4.0,
),
sliver: SliverList(
delegate: SliverChildListDelegate([
Text(
heroSubtitle!,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onBackground,
),
textAlign: TextAlign.start,
textAlign: hasHeroIcon ? TextAlign.center : TextAlign.start,
),
const SizedBox(height: 16.0),
...children,
]),
),
),
SliverPadding(
padding: const EdgeInsets.all(16.0),
sliver: SliverList(
delegate: SliverChildListDelegate(children),
),
),
],
),
);
}
}
class HeroSliverAppBar extends StatefulWidget {
const HeroSliverAppBar({
required this.heroTitle,
required this.hasHeroIcon,
required this.hasBackButton,
required this.onBackButtonPressed,
required this.heroIconWidget,
final super.key,
});
final String heroTitle;
final bool hasHeroIcon;
final bool hasBackButton;
final VoidCallback? onBackButtonPressed;
final Widget heroIconWidget;
@override
State<HeroSliverAppBar> createState() => _HeroSliverAppBarState();
}
class _HeroSliverAppBarState extends State<HeroSliverAppBar> {
Size _size = Size.zero;
@override
Widget build(final BuildContext context) => SliverAppBar(
expandedHeight:
widget.hasHeroIcon ? 148.0 + _size.height : 72.0 + _size.height,
primary: true,
pinned: true,
stretch: true,
leading: widget.hasBackButton
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: widget.onBackButtonPressed ??
() => Navigator.of(context).pop(),
)
: null,
flexibleSpace: FlexibleSpaceBar(
title: LayoutBuilder(
builder: (final context, final constraints) => SizedBox(
width: constraints.maxWidth - 72.0,
child: WidgetSize(
onChange: (final Size size) => setState(() => _size = size),
child: Text(
widget.heroTitle,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
overflow: TextOverflow.fade,
textAlign: TextAlign.center,
),
),
),
),
expandedTitleScale: 1.2,
centerTitle: true,
collapseMode: CollapseMode.pin,
titlePadding: const EdgeInsets.only(
bottom: 12.0,
top: 16.0,
),
background: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 72.0),
if (widget.hasHeroIcon) widget.heroIconWidget,
],
),
),

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
class WidgetSize extends StatefulWidget {
const WidgetSize({
required this.onChange,
required this.child,
final super.key,
});
final Widget child;
final Function onChange;
@override
State<WidgetSize> createState() => _WidgetSizeState();
}
class _WidgetSizeState extends State<WidgetSize> {
@override
Widget build(final BuildContext context) {
SchedulerBinding.instance.addPostFrameCallback(postFrameCallback);
return Container(
key: widgetKey,
child: widget.child,
);
}
var widgetKey = GlobalKey();
Size? oldSize;
void postFrameCallback(_) {
final context = widgetKey.currentContext;
if (context == null) {
return;
}
;
final newSize = context.size;
if (oldSize == newSize) {
return;
}
oldSize = newSize;
widget.onChange(newSize);
}
}

View File

@ -91,7 +91,6 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
if (!isReady) {
return BrandHeroScreen(
hasBackButton: true,
headerTitle: '',
heroIcon: BrandIcons.globe,
heroTitle: 'domain.screen_title'.tr(),
heroSubtitle: 'not_ready_card.in_menu'.tr(),

View File

@ -16,7 +16,8 @@ class AboutApplicationPage extends StatelessWidget {
preferredSize: const Size.fromHeight(52),
child: BrandHeader(
title: 'about_application_page.title'.tr(),
hasBackButton: true),
hasBackButton: true,
),
),
body: ListView(
padding: paddingH15V0,

View File

@ -12,7 +12,6 @@ import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/ui/components/brand_button/segmented_buttons.dart';
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';

View File

@ -47,14 +47,18 @@ class _SelectTimezoneState extends State<SelectTimezone> {
@override
Widget build(final BuildContext context) => Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(52),
child: BrandHeader(
title: 'server.select_timezone'.tr(),
hasBackButton: true,
appBar: AppBar(
title: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Text('server.select_timezone'.tr()),
),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
),
body: ListView(
body: SafeArea(
child: ListView(
controller: controller,
children: locations
.asMap()
@ -124,5 +128,6 @@ class _SelectTimezoneState extends State<SelectTimezone> {
.values
.toList(),
),
),
);
}

View File

@ -47,25 +47,14 @@ class _ServicePageState extends State<ServicePage> {
return BrandHeroScreen(
hasBackButton: true,
children: [
Container(
alignment: Alignment.center,
child: SvgPicture.string(
heroIconWidget: SvgPicture.string(
service.svgIcon,
width: 48.0,
height: 48.0,
color: Theme.of(context).colorScheme.onBackground,
),
),
const SizedBox(height: 16),
Text(
service.displayName,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium!.copyWith(
color: Theme.of(context).colorScheme.onBackground,
),
),
const SizedBox(height: 16),
heroTitle: service.displayName,
children: [
ServiceStatusCard(status: service.status),
const SizedBox(height: 16),
if (service.url != null)

View File

@ -415,7 +415,8 @@ class InitializingPage extends StatelessWidget {
BrandText.h2('initializing.create_master_account'.tr()),
const SizedBox(height: 10),
BrandText.body2(
'initializing.enter_nickname_and_password'.tr()),
'initializing.enter_nickname_and_password'.tr(),
),
const Spacer(),
CubitFormTextField(
formFieldCubit: context.read<RootUserFormCubit>().userName,