diff --git a/assets/images/logos/digital_ocean.svg b/assets/images/logos/digital_ocean.svg new file mode 100644 index 00000000..98b04c36 --- /dev/null +++ b/assets/images/logos/digital_ocean.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/logos/hetzner.svg b/assets/images/logos/hetzner.svg new file mode 100644 index 00000000..5cafc101 --- /dev/null +++ b/assets/images/logos/hetzner.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/translations/en.json b/assets/translations/en.json index 1b596cba..9c3d5e6a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -4,6 +4,7 @@ "basis": { "providers": "Providers", "providers_title": "Your Data Center", + "select": "Select", "services": "Services", "services_title": "Your personal, private and independent services.", "users": "Users", @@ -79,8 +80,14 @@ "onboarding": { "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_title": "SelfPrivacy is not a cloud, it's Your personal datacenter", + "page2_text": "SelfPrivacy only works with providers that you choose. If you do not have required accounts in those, we'll help you to create them.", + "page2_server_provider_title": "Server provider", + "page2_server_provider_text": "A server provider maintains your server in its own data center. SelfPrivacy will automatically connect to the provider and setup all necessary things.", + "page2_dns_provider_title": "DNS provider", + "page2_dns_provider_text": "You need a domain to have a place in the Internet. And you also need a reliable DNS provider to have the domain pointed to your server. We will suggest you pick a supported DNS provider to automatically setup networking.", + "page2_backup_provider_title": "Backup provider", + "page2_backup_provider_text": "What if something happens to your server? Imagine a hacker attack, an accidental data deletion or denial of service? Your data will be kept safe in your provider of backups. They will be securely encrypted and anytime accessible to restore your server with." }, "resource_chart": { "month": "Month", @@ -268,20 +275,45 @@ "no_ssh_notice": "Only email and SSH accounts are created for this user. Single Sign On for all services is coming soon." }, "initializing": { - "connect_to_server": "Connect a server", - "select_provider": "Select your provider", - "place_where_data": "A place where your data and SelfPrivacy services will reside:", + "connect_to_server": "Let's start with a server.", + "select_provider": "Pick any provider from the following list, they all support SelfPrivacy", + "select_provider_notice": "By 'Relatively small' we mean a machine with 2 cores of CPU and 2 gigabytes of RAM.", + "select_provider_countries_title": "Available countries", + "select_provider_countries_text_hetzner": "Germany, Finland, USA", + "select_provider_countries_text_do": "USA, Netherlands, Singapore, UK, Germany, Canada, India, Australia", + "select_provider_price_title": "Average price", + "select_provider_price_text_hetzner": "€8 per month for a relatively small server and 50GB of disk storage", + "select_provider_price_text_do": "$17 per month for a relatively small server and 50GB of disk storage", + "select_provider_payment_title": "Payment methods", + "select_provider_payment_text_hetzner": "Credit cards, SWIFT, SEPA, PayPal", + "select_provider_payment_text_do": "Credit cards, Google Pay, PayPal", + "select_provider_email_notice": "E-mail hosting won't be available for new clients. Nevertheless it will be unlocked as soon as you complete your first payment.", + "select_provider_site_button": "Visit site", + "connect_to_server_provider": "Autorize in ", + "connect_to_server_provider_text": "With API token SelfPrivacy will be able to rent a machine and setup your server on it", "how": "How to obtain API token", "provider_bad_key_error": "Provider API key is invalid", "could_not_connect": "Counldn't connect to the provider.", - "choose_location_type": "Choose your server location and type:", - "back_to_locations": "Go back to available locations!", - "no_locations_found": "No available locations found. Make sure your account is accessible.", + "choose_location_type": "Where do you want to order your server?", + "choose_location_type_text": "Different locations provide different server configurations, prices and connection speed.", + "locations_not_found": "Oops!", + "locations_not_found_text": "There are no available servers to rent", + "back_to_locations": "Select something else", + "no_locations_found": "No available locations found, make sure your account is accessible", + "choose_server_type": "What type of server do you need?", + "choose_server_type_text": "Different resource capabilities support different services. Don't worry, you can expand your server anytime", + "choose_server_type_notice": "The important things to look at are the CPU and RAM. The data of your services will be stored on a mounted volume which is easily explandable and gets paid for separately.", + "choose_server_type_ram": "{} GB of RAM", + "choose_server_type_storage": "{} GB of system storage", + "choose_server_type_payment_per_month": "{} per month", "no_server_types_found": "No available server types found. Make sure your account is accessible and try to change your server location.", "cloudflare_bad_key_error": "Cloudflare API key is invalid", "backblaze_bad_key_error": "Backblaze storage information is invalid", - "connect_cloudflare": "Connect CloudFlare", + "select_dns": "Now let's select a DNS provider", + "select_dns_text": "", "manage_domain_dns": "To manage your domain's DNS", + "use_this_domain": "Use this domain?", + "use_this_domain_text": "The token you provided gives access to the following domain", "cloudflare_api_token": "CloudFlare API Token", "connect_backblaze_storage": "Connect Backblaze storage", "no_connected_domains": "No connected domains at the moment", @@ -444,4 +476,4 @@ "length_not_equal": "Length is [], should be {}", "length_longer": "Length is [], should be shorter than or equal to {}" } -} \ No newline at end of file +} diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 8764580a..3ab94069 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -3,6 +3,7 @@ "locale": "ru", "basis": { "providers": "Провайдеры", + "select": "Выбрать", "providers_title": "Ваш Дата Центр", "services": "Сервисы", "services_title": "Ваши личные, приватные и независимые сервисы.", @@ -80,7 +81,13 @@ "page1_title": "Цифровая независимость доступна каждому", "page1_text": "Почта, VPN, Мессенджер, социальная сеть и многое другое на Вашем личном сервере, под Вашим полным контролем.", "page2_title": "SelfPrivacy — это не облако, а Ваш личный дата-центр", - "page2_text": "SelfPrivacy работает только с вашими сервис-провайдерами: Hetzner, Cloudflare, Backblaze. Если у Вас нет учётных записей, мы поможем их создать." + "page2_text": "SelfPrivacy работает только с сервис-провайдерами на ваш выбор. Если у Вас нет учётных записей, мы поможем их создать.", + "page2_server_provider_title": "Сервер-провайдер", + "page2_server_provider_text": "Сервер-провайдер будет обслуживать ваш сервер в своём дата-центре. SelfPrivacy автоматически подключится к нему и настроит вам сервер.", + "page2_dns_provider_title": "DNS-провайдер", + "page2_dns_provider_text": "Чтобы быть в интернете, нужен домен. Чтобы домен указывал на ваш сервер, нужен надёжный DNS сервер. Мы предложим вам выбрать один из поддерживаемых DNS серверов автоматически настроим все записи. Хотите настроить их вручную? Так тоже можно.", + "page2_backup_provider_title": "Бэкап-провайдер", + "page2_backup_provider_text": "Что если с сервером что-то случится? Хакерская атака, отказ в обслуживании или просто случайное удаление данных? Ваши данные будут в сохранности в другом месте, у провайдера хранилища ваших резервных копий. Все они надёжно шифруются, и вы сможете восстановить свой сервер." }, "resource_chart": { "month": "Месяц", @@ -268,19 +275,43 @@ "no_ssh_notice": "Для этого пользователя созданы только SSH и Email аккаунты. Единая авторизация для всех сервисов ещё не реализована." }, "initializing": { - "connect_to_server": "Подключите сервер", - "place_where_data": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:", + "connect_to_server": "Начнём с сервера.", + "select_provider": "Ниже подборка провайдеров, которых поддерживает SelfPrivacy", + "select_provider_notice": "Под 'Небольшим сервером' имеется ввиду сервер с двумя потоками процессора и двумя гигабайтами оперативной памяти.", + "select_provider_countries_title": "Доступные страны", + "select_provider_countries_text_hetzner": "Германия, Финляндия, США", + "select_provider_countries_text_do": "США, Нидерланды, Сингапур, Великобритания, Германия, Канада, Индия, Австралия", + "select_provider_price_title": "Средняя цена", + "select_provider_price_text_hetzner": "€8 в месяц за небольшой сервер и 50GB места на диске", + "select_provider_price_text_do": "$17 в месяц за небольшой сервер и 50GB места на диске", + "select_provider_payment_title": "Методы оплаты", + "select_provider_payment_text_hetzner": "Банковские карты, SWIFT, SEPA, PayPal", + "select_provider_payment_text_do": "Банковские карты, Google Pay, PayPal", + "select_provider_email_notice": "Хостинг электронной почты недоступен для новых клиентов. Разблокировать можно будет после первой оплаты.", + "select_provider_site_button": "Посетить сайт", + "connect_to_server_provider": "Авторизоваться в ", + "connect_to_server_provider_text": "С помощью API токена приложение SelfPrivacy сможет от вашего имени заказать и настроить сервер", "how": "Как получить API Token", "provider_bad_key_error": "API ключ провайдера неверен", "could_not_connect": "Не удалось соединиться с провайдером.", - "choose_location_type": "Выберите локацию и тип вашего сервера:", - "back_to_locations": "Назад к доступным локациям!", + "choose_location_type": "Где заказать сервер?", + "choose_location_type_text": "От выбора локации будут зависеть доступные конфигурации, цены и скорость вашего соединения с сервером.", + "locations_not_found": "Упс!", + "locations_not_found_text": "В этом месте не оказалось доступных серверов для аренды", + "back_to_locations": "Выберем другой", "no_locations_found": "Не найдено локаций. Убедитесь, что ваш аккаунт доступен.", - "no_server_types_found": "Не удалось получить список серверов. Убедитесь, что ваш аккаунт доступен и попытайтесь сменить локацию сервера.", + "choose_server_type": "Какой выбрать тип сервера?", + "choose_server_type_text": "От ресурсов сервера зависит, какие сервисы смогут запуститься. Расширить сервер можно будет в любое время", + "choose_server_type_notice": "Главное, на что стоит обратить внимание — количество потоков процессора и объём оперативной памяти. Данные сервисов будут размещены на отдельном диске, который оплачивается отдельно и легко расширяем!", + "choose_server_type_ram": "{} GB у RAM", + "choose_server_type_storage": "{} GB системного хранилища", + "choose_server_type_payment_per_month": "{} в месяц", + "no_server_types_found": "Не найдено доступных типов сервера! Пожалуйста, убедитесь, что у вас есть доступ к провайдеру сервера...", "cloudflare_bad_key_error": "Cloudflare API ключ неверен", "backblaze_bad_key_error": "Информация о Backblaze хранилище неверна", - "connect_cloudflare": "Подключите CloudFlare", "manage_domain_dns": "Для управления DNS вашего домена", + "use_this_domain": "Используем этот домен?", + "use_this_domain_text": "Указанный вами токен даёт контроль над этим доменом", "cloudflare_api_token": "CloudFlare API ключ", "connect_backblaze_storage": "Подключите облачное хранилище Backblaze", "no_connected_domains": "На данный момент подлюченных доменов нет", diff --git a/fastlane/metadata/android/en-US/changelogs/0.8.0.txt b/fastlane/metadata/android/en-US/changelogs/0.8.0.txt new file mode 100644 index 00000000..e7d8dbad --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/0.8.0.txt @@ -0,0 +1,33 @@ +Server setup: +- Added support for Digital Ocean as server provider +- You can now choose server region +- You can now choose server tier +- Server installation UI has been refreshed +- Fields now have more specific error messages + +Common UI: +- New app bar used in most of the screens + +Services: +- Services are now sorted by their status + +Server settings: +- Timezone search screen now has a search bar +- Fixed job creation when switching the setting multiple times +- Server destruction now works + +Jobs: +- Jobs panel now should take slightly less space + +Auth: +- Recovery key page can now be reloaded by dragging down + +Logging: +- Log console now has a limit of 500 lines +- GraphQL API requests are now logged in the console +- Networks errors are better handled + +For developers: +- App now only uses GraphQL API to communicate with the server. All REST API calls have been removed. +- Server can now be deployed with staging ACME certificates +- Language assets have been reorganized diff --git a/lib/illustrations/stray_deer.dart b/lib/illustrations/stray_deer.dart new file mode 100644 index 00000000..88fd55c3 --- /dev/null +++ b/lib/illustrations/stray_deer.dart @@ -0,0 +1,2895 @@ +import 'package:dynamic_color/dynamic_color.dart'; +import 'package:flutter/material.dart'; +import 'package:material_color_utilities/palettes/core_palette.dart'; + +// max_width coefficient is 1 +class StrayDeerPainter extends CustomPainter { + StrayDeerPainter({required this.colorPalette, required this.colorScheme}); + + final CorePalette colorPalette; + final ColorScheme colorScheme; + + @override + void paint(final Canvas canvas, final Size size) { + final Color deerTracks = Color(colorPalette.tertiary.get(70)); + final Color mailBag = Color(colorPalette.tertiary.get(80)); + final Color contourColor = Color(colorPalette.tertiary.get(10)); + final Color deerSkin = + const Color(0xffe0ac9c).harmonizeWith(colorScheme.primary); + + print('deerSkin: $deerSkin'); + print('colorScheme.primary: ${colorScheme.primary}'); + print('colorPalette.tertiary.get(10): ${colorPalette.tertiary.get(50)}'); + + final Path path0 = Path(); + path0.moveTo(size.width * 0.6099773, size.height * 0.6719577); + path0.lineTo(size.width * 0.6088435, size.height * 0.6719577); + path0.lineTo(size.width * 0.6148904, size.height * 0.6727135); + path0.lineTo(size.width * 0.6099773, size.height * 0.6719577); + path0.close(); + path0.moveTo(size.width * 0.5593348, size.height * 0.6723356); + path0.cubicTo( + size.width * 0.5525321, + size.height * 0.6723356, + size.width * 0.5461073, + size.height * 0.6738473, + size.width * 0.5400605, + size.height * 0.6761149, + ); + path0.lineTo(size.width * 0.5476190, size.height * 0.6806500); + path0.cubicTo( + size.width * 0.5529101, + size.height * 0.6798942, + size.width * 0.5585790, + size.height * 0.6806500, + size.width * 0.5634921, + size.height * 0.6787604, + ); + path0.cubicTo( + size.width * 0.5653817, + size.height * 0.6780045, + size.width * 0.5680272, + size.height * 0.6764928, + size.width * 0.5680272, + size.height * 0.6746032, + ); + path0.cubicTo( + size.width * 0.5680272, + size.height * 0.6727135, + size.width * 0.5653817, + size.height * 0.6727135, + size.width * 0.5642479, + size.height * 0.6727135, + ); + path0.lineTo(size.width * 0.5593348, size.height * 0.6727135); + path0.close(); + path0.moveTo(size.width * 0.6757370, size.height * 0.6727135); + path0.lineTo(size.width * 0.6700680, size.height * 0.6730915); + path0.cubicTo( + size.width * 0.6681784, + size.height * 0.6734694, + size.width * 0.6655329, + size.height * 0.6730915, + size.width * 0.6636432, + size.height * 0.6746032, + ); + path0.lineTo(size.width * 0.6636432, size.height * 0.6753590); + path0.lineTo(size.width * 0.6723356, size.height * 0.6810280); + path0.lineTo(size.width * 0.6874528, size.height * 0.6825397); + path0.cubicTo( + size.width * 0.6897203, + size.height * 0.6825397, + size.width * 0.6923658, + size.height * 0.6832955, + size.width * 0.6938776, + size.height * 0.6814059, + ); + path0.cubicTo( + size.width * 0.6953893, + size.height * 0.6798942, + size.width * 0.6931217, + size.height * 0.6776266, + size.width * 0.6919879, + size.height * 0.6772487, + ); + path0.arcToPoint( + Offset(size.width * 0.6757370, size.height * 0.6727135), + radius: Radius.elliptical( + size.width * 0.03325775, + size.height * 0.03325775, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.5971277, size.height * 0.6768707); + path0.cubicTo( + size.width * 0.5997732, + size.height * 0.6780045, + size.width * 0.6027967, + size.height * 0.6780045, + size.width * 0.6054422, + size.height * 0.6768707, + ); + path0.close(); + path0.moveTo(size.width * 0.4950869, size.height * 0.6814059); + path0.lineTo(size.width * 0.4924414, size.height * 0.6814059); + path0.cubicTo( + size.width * 0.4909297, + size.height * 0.6814059, + size.width * 0.4886621, + size.height * 0.6814059, + size.width * 0.4871504, + size.height * 0.6825397, + ); + path0.lineTo(size.width * 0.4833711, size.height * 0.6912320); + path0.cubicTo( + size.width * 0.4894180, + size.height * 0.6904762, + size.width * 0.4954649, + size.height * 0.6904762, + size.width * 0.5011338, + size.height * 0.6882086, + ); + path0.cubicTo( + size.width * 0.5030234, + size.height * 0.6874528, + size.width * 0.5049131, + size.height * 0.6866969, + size.width * 0.5064248, + size.height * 0.6851852, + ); + path0.cubicTo( + size.width * 0.5071807, + size.height * 0.6840514, + size.width * 0.5056689, + size.height * 0.6829176, + size.width * 0.5045351, + size.height * 0.6825397, + ); + path0.cubicTo( + size.width * 0.5015117, + size.height * 0.6817838, + size.width * 0.4984883, + size.height * 0.6814059, + size.width * 0.4950869, + size.height * 0.6814059, + ); + path0.close(); + path0.moveTo(size.width * 0.6303855, size.height * 0.6832955); + path0.arcToPoint( + Offset(size.width * 0.6179138, size.height * 0.6863190), + radius: Radius.elliptical( + size.width * 0.03401361, + size.height * 0.03401361, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.6167800, + size.height * 0.6866969, + size.width * 0.6148904, + size.height * 0.6874528, + size.width * 0.6148904, + size.height * 0.6889645, + ); + path0.cubicTo( + size.width * 0.6148904, + size.height * 0.6904762, + size.width * 0.6167800, + size.height * 0.6904762, + size.width * 0.6175359, + size.height * 0.6900983, + ); + path0.lineTo(size.width * 0.6179138, size.height * 0.6938776); + path0.cubicTo( + size.width * 0.6250945, + size.height * 0.6934996, + size.width * 0.6322751, + size.height * 0.6934996, + size.width * 0.6386999, + size.height * 0.6904762, + ); + path0.cubicTo( + size.width * 0.6398337, + size.height * 0.6900983, + size.width * 0.6417234, + size.height * 0.6889645, + size.width * 0.6413454, + size.height * 0.6874528, + ); + path0.cubicTo( + size.width * 0.6405896, + size.height * 0.6851852, + size.width * 0.6379441, + size.height * 0.6848073, + size.width * 0.6360544, + size.height * 0.6840514, + ); + path0.lineTo(size.width * 0.6303855, size.height * 0.6832955); + path0.close(); + path0.moveTo(size.width * 0.7959184, size.height * 0.6885865); + path0.lineTo(size.width * 0.7932729, size.height * 0.6889645); + path0.lineTo(size.width * 0.7932729, size.height * 0.6893424); + path0.lineTo(size.width * 0.7932729, size.height * 0.6893424); + path0.lineTo(size.width * 0.7951625, size.height * 0.6980348); + path0.arcToPoint( + Offset(size.width * 0.8148148, size.height * 0.7018141), + radius: Radius.elliptical( + size.width * 0.02116402, + size.height * 0.02116402, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.8163265, + size.height * 0.7010582, + size.width * 0.8178382, + size.height * 0.6999244, + size.width * 0.8170824, + size.height * 0.6980348, + ); + path0.cubicTo( + size.width * 0.8163265, + size.height * 0.6961451, + size.width * 0.8140590, + size.height * 0.6946334, + size.width * 0.8121693, + size.height * 0.6938776, + ); + path0.arcToPoint( + Offset(size.width * 0.7981859, size.height * 0.6885865), + radius: Radius.elliptical( + size.width * 0.03665911, + size.height * 0.03665911, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.lineTo(size.width * 0.7959184, size.height * 0.6885865); + path0.close(); + path0.moveTo(size.width * 0.7448980, size.height * 0.6900983); + path0.lineTo(size.width * 0.7430083, size.height * 0.6900983); + path0.cubicTo( + size.width * 0.7407407, + size.height * 0.6904762, + size.width * 0.7384732, + size.height * 0.6916100, + size.width * 0.7369615, + size.height * 0.6938776, + ); + path0.cubicTo( + size.width * 0.7365835, + size.height * 0.6938776, + size.width * 0.7369615, + size.height * 0.6946334, + size.width * 0.7369615, + size.height * 0.6946334, + ); + path0.lineTo(size.width * 0.7369615, size.height * 0.6999244); + path0.cubicTo( + size.width * 0.7418745, + size.height * 0.7006803, + size.width * 0.7467876, + size.height * 0.7014361, + size.width * 0.7520786, + size.height * 0.7006803, + ); + path0.cubicTo( + size.width * 0.7543462, + size.height * 0.7006803, + size.width * 0.7566138, + size.height * 0.6999244, + size.width * 0.7585034, + size.height * 0.6980348, + ); + path0.cubicTo( + size.width * 0.7600151, + size.height * 0.6969010, + size.width * 0.7585034, + size.height * 0.6953893, + size.width * 0.7573696, + size.height * 0.6942555, + ); + path0.cubicTo( + size.width * 0.7535903, + size.height * 0.6919879, + size.width * 0.7494331, + size.height * 0.6897203, + size.width * 0.7448980, + size.height * 0.6900983, + ); + path0.close(); + path0.moveTo(size.width * 0.4357521, size.height * 0.6961451); + path0.lineTo(size.width * 0.4349962, size.height * 0.7052154); + path0.cubicTo( + size.width * 0.4399093, + size.height * 0.7055933, + size.width * 0.4448224, + size.height * 0.7040816, + size.width * 0.4489796, + size.height * 0.7014361, + ); + path0.cubicTo( + size.width * 0.4504913, + size.height * 0.7010582, + size.width * 0.4523810, + size.height * 0.7003023, + size.width * 0.4531368, + size.height * 0.6991686, + ); + path0.cubicTo( + size.width * 0.4538927, + size.height * 0.6980348, + size.width * 0.4527589, + size.height * 0.6972789, + size.width * 0.4520030, + size.height * 0.6972789, + ); + path0.cubicTo( + size.width * 0.4489796, + size.height * 0.6961451, + size.width * 0.4459562, + size.height * 0.6972789, + size.width * 0.4433107, + size.height * 0.6965231, + ); + path0.lineTo(size.width * 0.4357521, size.height * 0.6961451); + path0.close(); + path0.moveTo(size.width * 0.3408919, size.height * 0.6999244); + path0.arcToPoint( + Offset(size.width * 0.3250189, size.height * 0.7052154), + radius: Radius.elliptical( + size.width * 0.03401361, + size.height * 0.03401361, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.lineTo(size.width * 0.3208617, size.height * 0.7108844); + path0.cubicTo( + size.width * 0.3465608, + size.height * 0.7146636, + size.width * 0.3522298, + size.height * 0.6999244, + size.width * 0.3408919, + size.height * 0.6999244, + ); + path0.close(); + path0.moveTo(size.width * 0.8435374, size.height * 0.7195767); + path0.cubicTo( + size.width * 0.8420257, + size.height * 0.7195767, + size.width * 0.8405140, + size.height * 0.7199546, + size.width * 0.8397581, + size.height * 0.7210884, + ); + path0.lineTo(size.width * 0.8344671, size.height * 0.7248677); + path0.cubicTo( + size.width * 0.8359788, + size.height * 0.7271353, + size.width * 0.8374906, + size.height * 0.7297808, + size.width * 0.8397581, + size.height * 0.7312925, + ); + path0.cubicTo( + size.width * 0.8416478, + size.height * 0.7328042, + size.width * 0.8446712, + size.height * 0.7324263, + size.width * 0.8473167, + size.height * 0.7324263, + ); + path0.cubicTo( + size.width * 0.8488284, + size.height * 0.7324263, + size.width * 0.8510960, + size.height * 0.7324263, + size.width * 0.8526077, + size.height * 0.7309146, + ); + path0.cubicTo( + size.width * 0.8541194, + size.height * 0.7286470, + size.width * 0.8533636, + size.height * 0.7260015, + size.width * 0.8522298, + size.height * 0.7241119, + ); + path0.arcToPoint( + Offset(size.width * 0.8431595, size.height * 0.7195767), + radius: Radius.elliptical( + size.width * 0.01020408, + size.height * 0.01020408, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.2883598, size.height * 0.7237339); + path0.cubicTo( + size.width * 0.2853364, + size.height * 0.7237339, + size.width * 0.2808012, + size.height * 0.7244898, + size.width * 0.2743764, + size.height * 0.7256236, + ); + path0.lineTo(size.width * 0.2660620, size.height * 0.7343159); + path0.cubicTo( + size.width * 0.2834467, + size.height * 0.7331822, + size.width * 0.3012094, + size.height * 0.7237339, + size.width * 0.2883598, + size.height * 0.7237339, + ); + path0.close(); + path0.moveTo(size.width * 0.8907785, size.height * 0.7241119); + path0.lineTo(size.width * 0.8892668, size.height * 0.7241119); + path0.lineTo(size.width * 0.8869992, size.height * 0.7278912); + path0.cubicTo( + size.width * 0.8881330, + size.height * 0.7312925, + size.width * 0.8904006, + size.height * 0.7331822, + size.width * 0.8926682, + size.height * 0.7350718, + ); + path0.cubicTo( + size.width * 0.8945578, + size.height * 0.7369615, + size.width * 0.8964475, + size.height * 0.7388511, + size.width * 0.8990930, + size.height * 0.7403628, + ); + path0.cubicTo( + size.width * 0.9006047, + size.height * 0.7411187, + size.width * 0.9028723, + size.height * 0.7422525, + size.width * 0.9043840, + size.height * 0.7418745, + ); + path0.cubicTo( + size.width * 0.9058957, + size.height * 0.7411187, + size.width * 0.9058957, + size.height * 0.7392290, + size.width * 0.9062736, + size.height * 0.7380952, + ); + path0.cubicTo( + size.width * 0.9062736, + size.height * 0.7339380, + size.width * 0.9047619, + size.height * 0.7294029, + size.width * 0.9009826, + size.height * 0.7271353, + ); + path0.cubicTo( + size.width * 0.8987150, + size.height * 0.7256236, + size.width * 0.8956916, + size.height * 0.7248677, + size.width * 0.8926682, + size.height * 0.7244898, + ); + path0.lineTo(size.width * 0.8907785, size.height * 0.7244898); + path0.close(); + path0.moveTo(size.width * 0.2078609, size.height * 0.7373394); + path0.cubicTo( + size.width * 0.2029478, + size.height * 0.7388511, + size.width * 0.1976568, + size.height * 0.7388511, + size.width * 0.1931217, + size.height * 0.7414966, + ); + path0.cubicTo( + size.width * 0.1908541, + size.height * 0.7430083, + size.width * 0.1893424, + size.height * 0.7464097, + size.width * 0.1912320, + size.height * 0.7486772, + ); + path0.cubicTo( + size.width * 0.1931217, + size.height * 0.7509448, + size.width * 0.1965231, + size.height * 0.7513228, + size.width * 0.1991686, + size.height * 0.7517007, + ); + path0.cubicTo( + size.width * 0.2048375, + size.height * 0.7517007, + size.width * 0.2105064, + size.height * 0.7517007, + size.width * 0.2154195, + size.height * 0.7490552, + ); + path0.arcToPoint( + Offset(size.width * 0.2214664, size.height * 0.7452759), + radius: Radius.elliptical( + size.width * 0.02645503, + size.height * 0.02645503, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.2226002, + size.height * 0.7445200, + size.width * 0.2237339, + size.height * 0.7422525, + size.width * 0.2222222, + size.height * 0.7407407, + ); + path0.cubicTo( + size.width * 0.2203326, + size.height * 0.7388511, + size.width * 0.2173091, + size.height * 0.7380952, + size.width * 0.2146636, + size.height * 0.7384732, + ); + path0.cubicTo( + size.width * 0.2135299, + size.height * 0.7384732, + size.width * 0.2123961, + size.height * 0.7392290, + size.width * 0.2116402, + size.height * 0.7399849, + ); + path0.close(); + path0.moveTo(size.width * 0.1583522, size.height * 0.7392290); + path0.cubicTo( + size.width * 0.1572184, + size.height * 0.7392290, + size.width * 0.1564626, + size.height * 0.7392290, + size.width * 0.1553288, + size.height * 0.7399849, + ); + path0.cubicTo( + size.width * 0.1545729, + size.height * 0.7403628, + size.width * 0.1541950, + size.height * 0.7411187, + size.width * 0.1541950, + size.height * 0.7422525, + ); + path0.lineTo(size.width * 0.1466364, size.height * 0.7422525); + path0.cubicTo( + size.width * 0.1436130, + size.height * 0.7441421, + size.width * 0.1405896, + size.height * 0.7460317, + size.width * 0.1379441, + size.height * 0.7490552, + ); + path0.cubicTo( + size.width * 0.1364324, + size.height * 0.7505669, + size.width * 0.1341648, + size.height * 0.7528345, + size.width * 0.1341648, + size.height * 0.7551020, + ); + path0.cubicTo( + size.width * 0.1349206, + size.height * 0.7573696, + size.width * 0.1371882, + size.height * 0.7577475, + size.width * 0.1390779, + size.height * 0.7577475, + ); + path0.cubicTo( + size.width * 0.1451247, + size.height * 0.7577475, + size.width * 0.1504157, + size.height * 0.7554800, + size.width * 0.1557067, + size.height * 0.7520786, + ); + path0.cubicTo( + size.width * 0.1579743, + size.height * 0.7505669, + size.width * 0.1594860, + size.height * 0.7482993, + size.width * 0.1617536, + size.height * 0.7464097, + ); + path0.cubicTo( + size.width * 0.1628874, + size.height * 0.7448980, + size.width * 0.1647770, + size.height * 0.7426304, + size.width * 0.1628874, + size.height * 0.7407407, + ); + path0.arcToPoint( + Offset(size.width * 0.1583522, size.height * 0.7392290), + radius: Radius.elliptical( + size.width * 0.007558579, + size.height * 0.007558579, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.8764172, size.height * 0.7505669); + path0.lineTo(size.width * 0.8726379, size.height * 0.7532124); + path0.cubicTo( + size.width * 0.8737717, + size.height * 0.7569917, + size.width * 0.8733938, + size.height * 0.7615268, + size.width * 0.8756614, + size.height * 0.7645503, + ); + path0.lineTo(size.width * 0.8794407, size.height * 0.7694633); + path0.cubicTo( + size.width * 0.8809524, + size.height * 0.7705971, + size.width * 0.8832200, + size.height * 0.7717309, + size.width * 0.8851096, + size.height * 0.7705971, + ); + path0.cubicTo( + size.width * 0.8862434, + size.height * 0.7694633, + size.width * 0.8866213, + size.height * 0.7675737, + size.width * 0.8862434, + size.height * 0.7660620, + ); + path0.cubicTo( + size.width * 0.8862434, + size.height * 0.7630385, + size.width * 0.8847317, + size.height * 0.7600151, + size.width * 0.8832200, + size.height * 0.7573696, + ); + path0.cubicTo( + size.width * 0.8824641, + size.height * 0.7547241, + size.width * 0.8809524, + size.height * 0.7520786, + size.width * 0.8783069, + size.height * 0.7513228, + ); + path0.arcToPoint( + Offset(size.width * 0.8764172, size.height * 0.7509448), + radius: Radius.elliptical( + size.width * 0.007558579, + size.height * 0.007558579, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.1190476, size.height * 0.7709751); + path0.cubicTo( + size.width * 0.1190476, + size.height * 0.7709751, + size.width * 0.1190476, + size.height * 0.7709751, + size.width * 0.1190476, + size.height * 0.7709751, + ); + path0.cubicTo( + size.width * 0.1171580, + size.height * 0.7709751, + size.width * 0.1156463, + size.height * 0.7713530, + size.width * 0.1145125, + size.height * 0.7721088, + ); + path0.lineTo(size.width * 0.1141345, size.height * 0.7728647); + path0.lineTo(size.width * 0.1111111, size.height * 0.7739985); + path0.cubicTo( + size.width * 0.1092215, + size.height * 0.7762661, + size.width * 0.1073318, + size.height * 0.7785336, + size.width * 0.1065760, + size.height * 0.7815571, + ); + path0.cubicTo( + size.width * 0.1061980, + size.height * 0.7834467, + size.width * 0.1065760, + size.height * 0.7853364, + size.width * 0.1080877, + size.height * 0.7860922, + ); + path0.cubicTo( + size.width * 0.1095994, + size.height * 0.7868481, + size.width * 0.1114890, + size.height * 0.7860922, + size.width * 0.1130008, + size.height * 0.7853364, + ); + path0.cubicTo( + size.width * 0.1156463, + size.height * 0.7834467, + size.width * 0.1182918, + size.height * 0.7815571, + size.width * 0.1205593, + size.height * 0.7785336, + ); + path0.cubicTo( + size.width * 0.1213152, + size.height * 0.7766440, + size.width * 0.1220711, + size.height * 0.7747543, + size.width * 0.1216931, + size.height * 0.7728647, + ); + path0.cubicTo( + size.width * 0.1216931, + size.height * 0.7713530, + size.width * 0.1201814, + size.height * 0.7709751, + size.width * 0.1190476, + size.height * 0.7709751, + ); + path0.close(); + path0.moveTo(size.width * 0.9213908, size.height * 0.7739985); + path0.lineTo(size.width * 0.9172336, size.height * 0.7758881); + path0.cubicTo( + size.width * 0.9142101, + size.height * 0.7808012, + size.width * 0.9126984, + size.height * 0.7868481, + size.width * 0.9123205, + size.height * 0.7925170, + ); + path0.cubicTo( + size.width * 0.9123205, + size.height * 0.7940287, + size.width * 0.9111867, + size.height * 0.7962963, + size.width * 0.9123205, + size.height * 0.7974301, + ); + path0.cubicTo( + size.width * 0.9138322, + size.height * 0.7981859, + size.width * 0.9157218, + size.height * 0.7974301, + size.width * 0.9168556, + size.height * 0.7970522, + ); + path0.arcToPoint( + Offset(size.width * 0.9263039, size.height * 0.7845805), + radius: Radius.elliptical( + size.width * 0.01511716, + size.height * 0.01511716, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.9263039, + size.height * 0.7808012, + size.width * 0.9259259, + size.height * 0.7770219, + size.width * 0.9229025, + size.height * 0.7743764, + ); + path0.arcToPoint( + Offset(size.width * 0.9213908, size.height * 0.7743764), + radius: Radius.elliptical( + size.width * 0.002267574, + size.height * 0.002267574, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.1511716, size.height * 0.7902494); + path0.lineTo(size.width * 0.1451247, size.height * 0.8027211); + path0.cubicTo( + size.width * 0.1466364, + size.height * 0.8061224, + size.width * 0.1485261, + size.height * 0.8099017, + size.width * 0.1519274, + size.height * 0.8117914, + ); + path0.cubicTo( + size.width * 0.1553288, + size.height * 0.8133031, + size.width * 0.1594860, + size.height * 0.8140590, + size.width * 0.1625094, + size.height * 0.8121693, + ); + path0.cubicTo( + size.width * 0.1643991, + size.height * 0.8114135, + size.width * 0.1651550, + size.height * 0.8091459, + size.width * 0.1651550, + size.height * 0.8072562, + ); + path0.cubicTo( + size.width * 0.1643991, + size.height * 0.8015873, + size.width * 0.1625094, + size.height * 0.7959184, + size.width * 0.1575964, + size.height * 0.7928949, + ); + path0.arcToPoint( + Offset(size.width * 0.1511716, size.height * 0.7902494), + radius: Radius.elliptical( + size.width * 0.01511716, + size.height * 0.01511716, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.8805745, size.height * 0.8008314); + path0.lineTo(size.width * 0.8779289, size.height * 0.8012094); + path0.arcToPoint( + Offset(size.width * 0.8643235, size.height * 0.8087680), + radius: Radius.elliptical( + size.width * 0.03665911, + size.height * 0.03665911, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.8635676, + size.height * 0.8099017, + size.width * 0.8643235, + size.height * 0.8110355, + size.width * 0.8650794, + size.height * 0.8110355, + ); + path0.cubicTo( + size.width * 0.8673469, + size.height * 0.8114135, + size.width * 0.8699924, + size.height * 0.8117914, + size.width * 0.8722600, + size.height * 0.8110355, + ); + path0.cubicTo( + size.width * 0.8752834, + size.height * 0.8102797, + size.width * 0.8779289, + size.height * 0.8087680, + size.width * 0.8798186, + size.height * 0.8065004, + ); + path0.cubicTo( + size.width * 0.8809524, + size.height * 0.8053666, + size.width * 0.8817082, + size.height * 0.8042328, + size.width * 0.8813303, + size.height * 0.8027211, + ); + path0.cubicTo( + size.width * 0.8813303, + size.height * 0.8019652, + size.width * 0.8805745, + size.height * 0.8012094, + size.width * 0.8809524, + size.height * 0.8008314, + ); + path0.close(); + path0.moveTo(size.width * 0.8030990, size.height * 0.8216175); + path0.lineTo(size.width * 0.7985639, size.height * 0.8227513); + path0.arcToPoint( + Offset(size.width * 0.7910053, size.height * 0.8276644), + radius: Radius.elliptical( + size.width * 0.02267574, + size.height * 0.02267574, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.7902494, + size.height * 0.8287982, + size.width * 0.7910053, + size.height * 0.8303099, + size.width * 0.7921391, + size.height * 0.8306878, + ); + path0.cubicTo( + size.width * 0.7947846, + size.height * 0.8321995, + size.width * 0.7974301, + size.height * 0.8321995, + size.width * 0.8004535, + size.height * 0.8318216, + ); + path0.cubicTo( + size.width * 0.8046107, + size.height * 0.8318216, + size.width * 0.8087680, + size.height * 0.8303099, + size.width * 0.8129252, + size.height * 0.8295540, + ); + path0.cubicTo( + size.width * 0.8140590, + size.height * 0.8291761, + size.width * 0.8155707, + size.height * 0.8280423, + size.width * 0.8136810, + size.height * 0.8272865, + ); + path0.lineTo(size.width * 0.8046107, size.height * 0.8216175); + path0.lineTo(size.width * 0.8030990, size.height * 0.8216175); + path0.close(); + path0.moveTo(size.width * 0.8499622, size.height * 0.8280423); + path0.cubicTo( + size.width * 0.8473167, + size.height * 0.8284203, + size.width * 0.8450491, + size.height * 0.8295540, + size.width * 0.8427816, + size.height * 0.8310658, + ); + path0.cubicTo( + size.width * 0.8405140, + size.height * 0.8321995, + size.width * 0.8382464, + size.height * 0.8340892, + size.width * 0.8374906, + size.height * 0.8363568, + ); + path0.cubicTo( + size.width * 0.8367347, + size.height * 0.8374906, + size.width * 0.8374906, + size.height * 0.8393802, + size.width * 0.8386243, + size.height * 0.8397581, + ); + path0.cubicTo( + size.width * 0.8408919, + size.height * 0.8401361, + size.width * 0.8435374, + size.height * 0.8397581, + size.width * 0.8458050, + size.height * 0.8393802, + ); + path0.cubicTo( + size.width * 0.8480726, + size.height * 0.8386243, + size.width * 0.8507181, + size.height * 0.8382464, + size.width * 0.8526077, + size.height * 0.8367347, + ); + path0.cubicTo( + size.width * 0.8544974, + size.height * 0.8356009, + size.width * 0.8563870, + size.height * 0.8340892, + size.width * 0.8575208, + size.height * 0.8321995, + ); + path0.cubicTo( + size.width * 0.8582766, + size.height * 0.8306878, + size.width * 0.8563870, + size.height * 0.8303099, + size.width * 0.8552532, + size.height * 0.8299320, + ); + path0.lineTo(size.width * 0.8533636, size.height * 0.8299320); + path0.close(); + path0.moveTo(size.width * 0.1375661, size.height * 0.8291761); + path0.cubicTo( + size.width * 0.1364324, + size.height * 0.8291761, + size.width * 0.1356765, + size.height * 0.8291761, + size.width * 0.1345427, + size.height * 0.8299320, + ); + path0.cubicTo( + size.width * 0.1341648, + size.height * 0.8299320, + size.width * 0.1334089, + size.height * 0.8306878, + size.width * 0.1334089, + size.height * 0.8314437, + ); + path0.lineTo(size.width * 0.1303855, size.height * 0.8352230); + path0.cubicTo( + size.width * 0.1296296, + size.height * 0.8374906, + size.width * 0.1315193, + size.height * 0.8397581, + size.width * 0.1334089, + size.height * 0.8412698, + ); + path0.lineTo(size.width * 0.1379441, size.height * 0.8450491); + path0.arcToPoint( + Offset(size.width * 0.1455026, size.height * 0.8480726), + radius: Radius.elliptical( + size.width * 0.01133787, + size.height * 0.01133787, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.1481481, + size.height * 0.8480726, + size.width * 0.1511716, + size.height * 0.8469388, + size.width * 0.1530612, + size.height * 0.8450491, + ); + path0.cubicTo( + size.width * 0.1541950, + size.height * 0.8431595, + size.width * 0.1530612, + size.height * 0.8412698, + size.width * 0.1523054, + size.height * 0.8393802, + ); + path0.cubicTo( + size.width * 0.1496599, + size.height * 0.8356009, + size.width * 0.1458806, + size.height * 0.8329554, + size.width * 0.1421013, + size.height * 0.8303099, + ); + path0.cubicTo( + size.width * 0.1409675, + size.height * 0.8295540, + size.width * 0.1390779, + size.height * 0.8291761, + size.width * 0.1375661, + size.height * 0.8291761, + ); + path0.close(); + path0.moveTo(size.width * 0.6749811, size.height * 0.8363568); + path0.lineTo(size.width * 0.6742252, size.height * 0.8363568); + path0.cubicTo( + size.width * 0.6708239, + size.height * 0.8363568, + size.width * 0.6674225, + size.height * 0.8363568, + size.width * 0.6643991, + size.height * 0.8378685, + ); + path0.lineTo(size.width * 0.6598639, size.height * 0.8405140); + path0.cubicTo( + size.width * 0.6606198, + size.height * 0.8416478, + size.width * 0.6621315, + size.height * 0.8424036, + size.width * 0.6636432, + size.height * 0.8427816, + ); + path0.lineTo(size.width * 0.6712018, size.height * 0.8446712); + path0.cubicTo( + size.width * 0.6749811, + size.height * 0.8458050, + size.width * 0.6798942, + size.height * 0.8461829, + size.width * 0.6836735, + size.height * 0.8442933, + ); + path0.cubicTo( + size.width * 0.6851852, + size.height * 0.8431595, + size.width * 0.6870748, + size.height * 0.8420257, + size.width * 0.6866969, + size.height * 0.8405140, + ); + path0.cubicTo( + size.width * 0.6866969, + size.height * 0.8386243, + size.width * 0.6848073, + size.height * 0.8378685, + size.width * 0.6829176, + size.height * 0.8374906, + ); + path0.cubicTo( + size.width * 0.6806500, + size.height * 0.8367347, + size.width * 0.6776266, + size.height * 0.8363568, + size.width * 0.6749811, + size.height * 0.8363568, + ); + path0.close(); + path0.moveTo(size.width * 0.2003023, size.height * 0.8401361); + path0.cubicTo( + size.width * 0.1984127, + size.height * 0.8401361, + size.width * 0.1965231, + size.height * 0.8401361, + size.width * 0.1946334, + size.height * 0.8412698, + ); + path0.cubicTo( + size.width * 0.1938776, + size.height * 0.8416478, + size.width * 0.1916100, + size.height * 0.8424036, + size.width * 0.1931217, + size.height * 0.8431595, + ); + path0.lineTo(size.width * 0.1931217, size.height * 0.8442933); + path0.cubicTo( + size.width * 0.1931217, + size.height * 0.8465608, + size.width * 0.1953893, + size.height * 0.8480726, + size.width * 0.1969010, + size.height * 0.8488284, + ); + path0.cubicTo( + size.width * 0.2006803, + size.height * 0.8503401, + size.width * 0.2044596, + size.height * 0.8510960, + size.width * 0.2082389, + size.height * 0.8507181, + ); + path0.cubicTo( + size.width * 0.2101285, + size.height * 0.8503401, + size.width * 0.2120181, + size.height * 0.8495843, + size.width * 0.2127740, + size.height * 0.8480726, + ); + path0.cubicTo( + size.width * 0.2135299, + size.height * 0.8458050, + size.width * 0.2123961, + size.height * 0.8439153, + size.width * 0.2105064, + size.height * 0.8427816, + ); + path0.cubicTo( + size.width * 0.2074830, + size.height * 0.8408919, + size.width * 0.2040816, + size.height * 0.8401361, + size.width * 0.2003023, + size.height * 0.8401361, + ); + path0.close(); + path0.moveTo(size.width * 0.5816327, size.height * 0.8439153); + path0.cubicTo( + size.width * 0.5782313, + size.height * 0.8439153, + size.width * 0.5752079, + size.height * 0.8446712, + size.width * 0.5721844, + size.height * 0.8450491, + ); + path0.cubicTo( + size.width * 0.5691610, + size.height * 0.8458050, + size.width * 0.5661376, + size.height * 0.8465608, + size.width * 0.5646259, + size.height * 0.8495843, + ); + path0.lineTo(size.width * 0.5661376, size.height * 0.8507181); + path0.lineTo(size.width * 0.5714286, size.height * 0.8522298); + path0.cubicTo( + size.width * 0.5752079, + size.height * 0.8533636, + size.width * 0.5789872, + size.height * 0.8537415, + size.width * 0.5827664, + size.height * 0.8533636, + ); + path0.arcToPoint( + Offset(size.width * 0.5903250, size.height * 0.8514739), + radius: Radius.elliptical( + size.width * 0.02267574, + size.height * 0.02267574, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.5918367, + size.height * 0.8507181, + size.width * 0.5933485, + size.height * 0.8492063, + size.width * 0.5922147, + size.height * 0.8476946, + ); + path0.cubicTo( + size.width * 0.5910809, + size.height * 0.8461829, + size.width * 0.5891912, + size.height * 0.8454271, + size.width * 0.5873016, + size.height * 0.8446712, + ); + path0.cubicTo( + size.width * 0.5854119, + size.height * 0.8439153, + size.width * 0.5835223, + size.height * 0.8439153, + size.width * 0.5816327, + size.height * 0.8439153, + ); + path0.close(); + path0.moveTo(size.width * 0.7403628, size.height * 0.8492063); + path0.cubicTo( + size.width * 0.7384732, + size.height * 0.8492063, + size.width * 0.7365835, + size.height * 0.8499622, + size.width * 0.7346939, + size.height * 0.8507181, + ); + path0.cubicTo( + size.width * 0.7324263, + size.height * 0.8510960, + size.width * 0.7309146, + size.height * 0.8544974, + size.width * 0.7328042, + size.height * 0.8567649, + ); + path0.cubicTo( + size.width * 0.7339380, + size.height * 0.8578987, + size.width * 0.7358277, + size.height * 0.8578987, + size.width * 0.7373394, + size.height * 0.8582766, + ); + path0.cubicTo( + size.width * 0.7426304, + size.height * 0.8590325, + size.width * 0.7482993, + size.height * 0.8594104, + size.width * 0.7524565, + size.height * 0.8571429, + ); + path0.cubicTo( + size.width * 0.7547241, + size.height * 0.8563870, + size.width * 0.7562358, + size.height * 0.8552532, + size.width * 0.7577475, + size.height * 0.8533636, + ); + path0.cubicTo( + size.width * 0.7585034, + size.height * 0.8518519, + size.width * 0.7566138, + size.height * 0.8510960, + size.width * 0.7554800, + size.height * 0.8507181, + ); + path0.lineTo(size.width * 0.7543462, size.height * 0.8507181); + path0.lineTo(size.width * 0.7418745, size.height * 0.8492063); + path0.lineTo(size.width * 0.7403628, size.height * 0.8492063); + path0.close(); + path0.moveTo(size.width * 0.3287982, size.height * 0.8552532); + path0.lineTo(size.width * 0.3208617, size.height * 0.8560091); + path0.cubicTo( + size.width * 0.3159486, + size.height * 0.8567649, + size.width * 0.3117914, + size.height * 0.8586546, + size.width * 0.3087680, + size.height * 0.8620559, + ); + path0.lineTo(size.width * 0.3087680, size.height * 0.8665911); + path0.lineTo(size.width * 0.3140590, size.height * 0.8665911); + path0.cubicTo( + size.width * 0.3208617, + size.height * 0.8650794, + size.width * 0.3276644, + size.height * 0.8647014, + size.width * 0.3340892, + size.height * 0.8624339, + ); + path0.cubicTo( + size.width * 0.3356009, + size.height * 0.8616780, + size.width * 0.3378685, + size.height * 0.8609221, + size.width * 0.3378685, + size.height * 0.8590325, + ); + path0.cubicTo( + size.width * 0.3382464, + size.height * 0.8571429, + size.width * 0.3359788, + size.height * 0.8560091, + size.width * 0.3340892, + size.height * 0.8556311, + ); + path0.lineTo(size.width * 0.3287982, size.height * 0.8556311); + path0.close(); + path0.moveTo(size.width * 0.3083900, size.height * 0.8665911); + path0.lineTo(size.width * 0.3083900, size.height * 0.8665911); + path0.close(); + path0.moveTo(size.width * 0.4546485, size.height * 0.8601663); + path0.cubicTo( + size.width * 0.4527589, + size.height * 0.8601663, + size.width * 0.4508692, + size.height * 0.8601663, + size.width * 0.4489796, + size.height * 0.8609221, + ); + path0.cubicTo( + size.width * 0.4463341, + size.height * 0.8616780, + size.width * 0.4436886, + size.height * 0.8631897, + size.width * 0.4433107, + size.height * 0.8658352, + ); + path0.lineTo(size.width * 0.4444444, size.height * 0.8684807); + path0.lineTo(size.width * 0.4493575, size.height * 0.8688587); + path0.cubicTo( + size.width * 0.4542706, + size.height * 0.8696145, + size.width * 0.4591837, + size.height * 0.8696145, + size.width * 0.4640967, + size.height * 0.8688587, + ); + path0.cubicTo( + size.width * 0.4659864, + size.height * 0.8688587, + size.width * 0.4678760, + size.height * 0.8681028, + size.width * 0.4693878, + size.height * 0.8662132, + ); + path0.cubicTo( + size.width * 0.4701436, + size.height * 0.8650794, + size.width * 0.4708995, + size.height * 0.8631897, + size.width * 0.4693878, + size.height * 0.8624339, + ); + path0.cubicTo( + size.width * 0.4671202, + size.height * 0.8613001, + size.width * 0.4644747, + size.height * 0.8613001, + size.width * 0.4618292, + size.height * 0.8609221, + ); + path0.lineTo(size.width * 0.4542706, size.height * 0.8601663); + path0.close(); + path0.moveTo(size.width * 0.2301587, size.height * 0.8654573); + path0.lineTo(size.width * 0.2290249, size.height * 0.8654573); + path0.cubicTo( + size.width * 0.2260015, + size.height * 0.8654573, + size.width * 0.2233560, + size.height * 0.8665911, + size.width * 0.2207105, + size.height * 0.8677249, + ); + path0.cubicTo( + size.width * 0.2199546, + size.height * 0.8677249, + size.width * 0.2191988, + size.height * 0.8681028, + size.width * 0.2207105, + size.height * 0.8677249, + ); + path0.lineTo(size.width * 0.2169312, size.height * 0.8722600); + path0.cubicTo( + size.width * 0.2184429, + size.height * 0.8749055, + size.width * 0.2214664, + size.height * 0.8760393, + size.width * 0.2241119, + size.height * 0.8760393, + ); + path0.cubicTo( + size.width * 0.2297808, + size.height * 0.8779289, + size.width * 0.2358277, + size.height * 0.8786848, + size.width * 0.2414966, + size.height * 0.8771731, + ); + path0.cubicTo( + size.width * 0.2437642, + size.height * 0.8767952, + size.width * 0.2460317, + size.height * 0.8764172, + size.width * 0.2467876, + size.height * 0.8745276, + ); + path0.cubicTo( + size.width * 0.2479214, + size.height * 0.8726379, + size.width * 0.2460317, + size.height * 0.8711262, + size.width * 0.2448980, + size.height * 0.8699924, + ); + path0.cubicTo( + size.width * 0.2411187, + size.height * 0.8662132, + size.width * 0.2354497, + size.height * 0.8654573, + size.width * 0.2297808, + size.height * 0.8654573, + ); + path0.close(); + path0.moveTo(size.width * 0.6326531, size.height * 0.8730159); + path0.lineTo(size.width * 0.6239607, size.height * 0.8741497); + path0.cubicTo( + size.width * 0.6201814, + size.height * 0.8749055, + size.width * 0.6160242, + size.height * 0.8760393, + size.width * 0.6126228, + size.height * 0.8790627, + ); + path0.lineTo(size.width * 0.6137566, size.height * 0.8828420); + path0.lineTo(size.width * 0.6190476, size.height * 0.8839758); + path0.lineTo(size.width * 0.6292517, size.height * 0.8843537); + path0.cubicTo( + size.width * 0.6337868, + size.height * 0.8843537, + size.width * 0.6386999, + size.height * 0.8839758, + size.width * 0.6417234, + size.height * 0.8805745, + ); + path0.cubicTo( + size.width * 0.6428571, + size.height * 0.8798186, + size.width * 0.6439909, + size.height * 0.8783069, + size.width * 0.6436130, + size.height * 0.8767952, + ); + path0.cubicTo( + size.width * 0.6428571, + size.height * 0.8749055, + size.width * 0.6402116, + size.height * 0.8749055, + size.width * 0.6386999, + size.height * 0.8741497, + ); + path0.cubicTo( + size.width * 0.6368103, + size.height * 0.8733938, + size.width * 0.6349206, + size.height * 0.8733938, + size.width * 0.6326531, + size.height * 0.8733938, + ); + path0.close(); + path0.moveTo(size.width * 0.6137566, size.height * 0.8832200); + path0.cubicTo( + size.width * 0.6137566, + size.height * 0.8832200, + size.width * 0.6137566, + size.height * 0.8832200, + size.width * 0.6137566, + size.height * 0.8832200, + ); + path0.lineTo(size.width * 0.6137566, size.height * 0.8832200); + path0.close(); + path0.moveTo(size.width * 0.6791383, size.height * 0.8783069); + path0.lineTo(size.width * 0.6798942, size.height * 0.8794407); + path0.lineTo(size.width * 0.6791383, size.height * 0.8783069); + path0.close(); + path0.moveTo(size.width * 0.6798942, size.height * 0.8794407); + path0.cubicTo( + size.width * 0.6814059, + size.height * 0.8813303, + size.width * 0.6825397, + size.height * 0.8835979, + size.width * 0.6844293, + size.height * 0.8851096, + ); + path0.lineTo(size.width * 0.6851852, size.height * 0.8858655); + path0.close(); + path0.moveTo(size.width * 0.6689342, size.height * 0.8801965); + path0.lineTo(size.width * 0.6746032, size.height * 0.8858655); + path0.lineTo(size.width * 0.6689342, size.height * 0.8801965); + path0.close(); + path0.moveTo(size.width * 0.3556311, size.height * 0.8801965); + path0.cubicTo( + size.width * 0.3529856, + size.height * 0.8801965, + size.width * 0.3503401, + size.height * 0.8805745, + size.width * 0.3480726, + size.height * 0.8820862, + ); + path0.cubicTo( + size.width * 0.3473167, + size.height * 0.8828420, + size.width * 0.3461829, + size.height * 0.8835979, + size.width * 0.3458050, + size.height * 0.8847317, + ); + path0.lineTo(size.width * 0.3427816, size.height * 0.8862434); + path0.arcToPoint( + Offset(size.width * 0.3616780, size.height * 0.8938020), + radius: Radius.elliptical( + size.width * 0.03590325, + size.height * 0.03590325, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.3654573, + size.height * 0.8945578, + size.width * 0.3692366, + size.height * 0.8956916, + size.width * 0.3730159, + size.height * 0.8938020, + ); + path0.cubicTo( + size.width * 0.3745276, + size.height * 0.8926682, + size.width * 0.3775510, + size.height * 0.8915344, + size.width * 0.3771731, + size.height * 0.8892668, + ); + path0.cubicTo( + size.width * 0.3771731, + size.height * 0.8869992, + size.width * 0.3749055, + size.height * 0.8854875, + size.width * 0.3733938, + size.height * 0.8847317, + ); + path0.arcToPoint( + Offset(size.width * 0.3556311, size.height * 0.8801965), + radius: Radius.elliptical( + size.width * 0.03476946, + size.height * 0.03476946, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.close(); + path0.moveTo(size.width * 0.4962207, size.height * 0.8832200); + path0.lineTo(size.width * 0.4913076, size.height * 0.8835979); + path0.cubicTo( + size.width * 0.4894180, + size.height * 0.8839758, + size.width * 0.4871504, + size.height * 0.8854875, + size.width * 0.4867725, + size.height * 0.8877551, + ); + path0.lineTo(size.width * 0.4875283, size.height * 0.8896447); + path0.lineTo(size.width * 0.4871504, size.height * 0.8900227); + path0.cubicTo( + size.width * 0.4867725, + size.height * 0.8915344, + size.width * 0.4894180, + size.height * 0.8919123, + size.width * 0.4909297, + size.height * 0.8926682, + ); + path0.arcToPoint( + Offset(size.width * 0.5045351, size.height * 0.8964475), + radius: Radius.elliptical( + size.width * 0.03401361, + size.height * 0.03401361, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path0.cubicTo( + size.width * 0.5079365, + size.height * 0.8964475, + size.width * 0.5117158, + size.height * 0.8964475, + size.width * 0.5143613, + size.height * 0.8945578, + ); + path0.cubicTo( + size.width * 0.5158730, + size.height * 0.8934240, + size.width * 0.5173847, + size.height * 0.8907785, + size.width * 0.5154951, + size.height * 0.8892668, + ); + path0.cubicTo( + size.width * 0.5128496, + size.height * 0.8873772, + size.width * 0.5098262, + size.height * 0.8862434, + size.width * 0.5064248, + size.height * 0.8851096, + ); + path0.cubicTo( + size.width * 0.5034014, + size.height * 0.8839758, + size.width * 0.4996221, + size.height * 0.8832200, + size.width * 0.4962207, + size.height * 0.8832200, + ); + path0.close(); + path0.moveTo(size.width * 0.6746032, size.height * 0.8858655); + path0.lineTo(size.width * 0.6749811, size.height * 0.8866213); + path0.close(); + + final Paint paint0Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint0Stroke.color = deerTracks.withOpacity(1); + paint0Stroke.strokeCap = StrokeCap.round; + paint0Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path0, paint0Stroke); + + final Path path_1 = Path(); + path_1.moveTo(size.width * 0.3605442, size.height * 0.4489796); + path_1.cubicTo( + size.width * 0.3594104, + size.height * 0.4667423, + size.width * 0.3439153, + size.height * 0.4690098, + size.width * 0.3367347, + size.height * 0.4708995, + ); + path_1.cubicTo( + size.width * 0.3227513, + size.height * 0.4232804, + size.width * 0.3053666, + size.height * 0.4395314, + size.width * 0.3193500, + size.height * 0.4765684, + ); + path_1.cubicTo( + size.width * 0.3072562, + size.height * 0.4811036, + size.width * 0.2800454, + size.height * 0.4882842, + size.width * 0.2702192, + size.height * 0.4916856, + ); + path_1.cubicTo( + size.width * 0.2653061, + size.height * 0.4848828, + size.width * 0.2426304, + size.height * 0.4622071, + size.width * 0.2195767, + size.height * 0.4656085, + ); + path_1.cubicTo( + size.width * 0.2044596, + size.height * 0.4640967, + size.width * 0.1836735, + size.height * 0.4648526, + size.width * 0.1855631, + size.height * 0.4754346, + ); + path_1.cubicTo( + size.width * 0.1965231, + size.height * 0.4863946, + size.width * 0.1825397, + size.height * 0.4962207, + size.width * 0.1885865, + size.height * 0.4965986, + ); + path_1.cubicTo( + size.width * 0.1613757, + size.height * 0.5086924, + size.width * 0.1545729, + size.height * 0.4523810, + size.width * 0.1405896, + size.height * 0.4523810, + ); + path_1.cubicTo( + size.width * 0.1315193, + size.height * 0.4572940, + size.width * 0.1462585, + size.height * 0.4973545, + size.width * 0.1311413, + size.height * 0.4807256, + ); + path_1.cubicTo( + size.width * 0.1164021, + size.height * 0.4769463, + size.width * 0.1148904, + size.height * 0.4331066, + size.width * 0.09977324, + size.height * 0.4452003, + ); + path_1.cubicTo( + size.width * 0.09599395, + size.height * 0.4656085, + size.width * 0.1095994, + size.height * 0.4867725, + size.width * 0.1239607, + size.height * 0.5003779, + ); + path_1.cubicTo( + size.width * 0.1409675, + size.height * 0.5162509, + size.width * 0.1678005, + size.height * 0.5060469, + size.width * 0.1844293, + size.height * 0.5192744, + ); + path_1.cubicTo( + size.width * 0.1825397, + size.height * 0.5347695, + size.width * 0.2014361, + size.height * 0.5495087, + size.width * 0.1908541, + size.height * 0.5650038, + ); + path_1.cubicTo( + size.width * 0.1870748, + size.height * 0.5740741, + size.width * 0.1825397, + size.height * 0.5831444, + size.width * 0.1961451, + size.height * 0.5831444, + ); + path_1.cubicTo( + size.width * 0.2082389, + size.height * 0.5914588, + size.width * 0.2278912, + size.height * 0.5922147, + size.width * 0.2377173, + size.height * 0.5967498, + ); + path_1.cubicTo( + size.width * 0.2460317, + size.height * 0.6107332, + size.width * 0.2728647, + size.height * 0.6148904, + size.width * 0.2626606, + size.height * 0.6360544, + ); + path_1.lineTo(size.width * 0.2539683, size.height * 0.7324263); + path_1.cubicTo( + size.width * 0.2743764, + size.height * 0.7384732, + size.width * 0.2811791, + size.height * 0.7150416, + size.width * 0.2834467, + size.height * 0.6999244, + ); + path_1.cubicTo( + size.width * 0.2860922, + size.height * 0.6900983, + size.width * 0.2879819, + size.height * 0.6651550, + size.width * 0.2966742, + size.height * 0.6662887, + ); + path_1.cubicTo( + size.width * 0.3053666, + size.height * 0.6787604, + size.width * 0.3042328, + size.height * 0.7154195, + size.width * 0.3257748, + size.height * 0.7067271, + ); + path_1.cubicTo( + size.width * 0.3446712, + size.height * 0.6972789, + size.width * 0.3253968, + size.height * 0.6757370, + size.width * 0.3257748, + size.height * 0.6602419, + ); + path_1.lineTo(size.width * 0.3125472, size.height * 0.6024187); + path_1.lineTo(size.width * 0.4070295, size.height * 0.6024187); + path_1.cubicTo( + size.width * 0.4085412, + size.height * 0.6364324, + size.width * 0.4089191, + size.height * 0.6734694, + size.width * 0.4104308, + size.height * 0.7071051, + ); + path_1.cubicTo( + size.width * 0.4323507, + size.height * 0.7142857, + size.width * 0.4436886, + size.height * 0.6874528, + size.width * 0.4410431, + size.height * 0.6693122, + ); + path_1.lineTo(size.width * 0.4470899, size.height * 0.6277400); + path_1.cubicTo( + size.width * 0.4569161, + size.height * 0.6466364, + size.width * 0.4557823, + size.height * 0.6712018, + size.width * 0.4720333, + size.height * 0.6863190, + ); + path_1.cubicTo( + size.width * 0.4939531, + size.height * 0.6832955, + size.width * 0.4890401, + size.height * 0.6693122, + size.width * 0.4833711, + size.height * 0.6428571, + ); + path_1.cubicTo( + size.width * 0.4803477, + size.height * 0.6050642, + size.width * 0.4708995, + size.height * 0.5684051, + size.width * 0.4618292, + size.height * 0.5321240, + ); + path_1.cubicTo( + size.width * 0.4792139, + size.height * 0.5192744, + size.width * 0.4811036, + size.height * 0.4943311, + size.width * 0.4693878, + size.height * 0.4773243, + ); + path_1.cubicTo( + size.width * 0.4576720, + size.height * 0.4546485, + size.width * 0.4455782, + size.height * 0.4848828, + size.width * 0.4467120, + size.height * 0.4977324, + ); + path_1.cubicTo( + size.width * 0.4489796, + size.height * 0.5211640, + size.width * 0.4202570, + size.height * 0.5000000, + size.width * 0.4070295, + size.height * 0.5011338, + ); + path_1.cubicTo( + size.width * 0.3941799, + size.height * 0.4973545, + size.width * 0.3556311, + size.height * 0.4890401, + size.width * 0.3537415, + size.height * 0.4848828, + ); + path_1.cubicTo( + size.width * 0.3813303, + size.height * 0.4716553, + size.width * 0.3854875, + size.height * 0.4648526, + size.width * 0.3771731, + size.height * 0.4402872, + ); + path_1.cubicTo( + size.width * 0.3654573, + size.height * 0.3873772, + size.width * 0.3439153, + size.height * 0.4021164, + size.width * 0.3605442, + size.height * 0.4489796, + ); + path_1.close(); + + final Paint paint1Fill = Paint()..style = PaintingStyle.fill; + paint1Fill.color = deerSkin.withOpacity(1); + canvas.drawPath(path_1, paint1Fill); + + final Path path_2 = Path(); + path_2.moveTo(size.width * 0.3624339, size.height * 0.4818594); + path_2.lineTo(size.width * 0.3492063, size.height * 0.4882842); + path_2.cubicTo( + size.width * 0.3616780, + size.height * 0.4886621, + size.width * 0.3775510, + size.height * 0.5090703, + size.width * 0.3760393, + size.height * 0.5192744, + ); + path_2.cubicTo( + size.width * 0.3548753, + size.height * 0.5222978, + size.width * 0.3325775, + size.height * 0.5283447, + size.width * 0.3178382, + size.height * 0.5241875, + ); + path_2.lineTo(size.width * 0.3114135, size.height * 0.5003779); + path_2.cubicTo( + size.width * 0.3076342, + size.height * 0.5011338, + size.width * 0.2944067, + size.height * 0.4992441, + size.width * 0.2981859, + size.height * 0.5064248, + ); + path_2.lineTo(size.width * 0.3057445, size.height * 0.5253212); + path_2.arcToPoint( + Offset(size.width * 0.2970522, size.height * 0.5423280), + radius: Radius.elliptical( + size.width * 0.01360544, + size.height * 0.01360544, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path_2.cubicTo( + size.width * 0.3004535, + size.height * 0.5748299, + size.width * 0.2898715, + size.height * 0.6345427, + size.width * 0.3393802, + size.height * 0.6194255, + ); + path_2.lineTo(size.width * 0.4168556, size.height * 0.6054422); + path_2.lineTo(size.width * 0.4259259, size.height * 0.5952381); + path_2.cubicTo( + size.width * 0.4229025, + size.height * 0.5718065, + size.width * 0.4236584, + size.height * 0.5623583, + size.width * 0.4202570, + size.height * 0.5385488, + ); + path_2.cubicTo( + size.width * 0.4179894, + size.height * 0.5306122, + size.width * 0.4115646, + size.height * 0.5166289, + size.width * 0.4036281, + size.height * 0.5185185, + ); + path_2.cubicTo( + size.width * 0.3998488, + size.height * 0.5177627, + size.width * 0.3956916, + size.height * 0.5177627, + size.width * 0.3915344, + size.height * 0.5177627, + ); + path_2.cubicTo( + size.width * 0.3885110, + size.height * 0.5068027, + size.width * 0.3862434, + size.height * 0.4920635, + size.width * 0.3794407, + size.height * 0.4882842, + ); + path_2.cubicTo( + size.width * 0.3771731, + size.height * 0.4867725, + size.width * 0.3643235, + size.height * 0.4837491, + size.width * 0.3624339, + size.height * 0.4818594, + ); + path_2.close(); + + final Paint paint2Fill = Paint()..style = PaintingStyle.fill; + paint2Fill.color = mailBag.withOpacity(1); + canvas.drawPath(path_2, paint2Fill); + + final Path path3 = Path(); + path3.moveTo(size.width * 0.2872260, size.height * 0.8212396); + path3.cubicTo( + size.width * 0.2917611, + size.height * 0.8193500, + size.width * 0.2966742, + size.height * 0.8189720, + size.width * 0.3015873, + size.height * 0.8201058, + ); + path3.lineTo(size.width * 0.3091459, size.height * 0.8219955); + path3.moveTo(size.width * 0.3212396, size.height * 0.8072562); + path3.arcToPoint( + Offset(size.width * 0.3696145, size.height * 0.8174603), + radius: Radius.elliptical( + size.width * 0.09070295, + size.height * 0.09070295, + ), + rotation: 0, + largeArc: false, + clockwise: true, + ); + path3.moveTo(size.width * 0.3624339, size.height * 0.8034769); + path3.cubicTo( + size.width * 0.3673469, + size.height * 0.8049887, + size.width * 0.3722600, + size.height * 0.8065004, + size.width * 0.3764172, + size.height * 0.8099017, + ); + path3.lineTo(size.width * 0.3813303, size.height * 0.8136810); + + final Paint paint3Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint3Stroke.color = deerTracks.withOpacity(1); + paint3Stroke.strokeCap = StrokeCap.round; + paint3Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path3, paint3Stroke); + + final Path path4 = Path(); + path4.moveTo(size.width * 0.2437642, size.height * 0.6077098); + path4.arcToPoint( + Offset(size.width * 0.2634165, size.height * 0.6167800), + radius: Radius.elliptical( + size.width * 0.02947846, + size.height * 0.02947846, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + + final Paint paint4Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint4Stroke.color = contourColor.withOpacity(1); + paint4Stroke.strokeCap = StrokeCap.round; + paint4Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path4, paint4Stroke); + + final Path path5 = Path(); + path5.moveTo(size.width * 0.2653061, size.height * 0.6046863); + path5.cubicTo( + size.width * 0.2603930, + size.height * 0.6455026, + size.width * 0.2551020, + size.height * 0.6878307, + size.width * 0.2524565, + size.height * 0.7282691, + ); + path5.moveTo(size.width * 0.2464097, size.height * 0.7312925); + path5.cubicTo( + size.width * 0.2569917, + size.height * 0.7369615, + size.width * 0.2671958, + size.height * 0.7339380, + size.width * 0.2773998, + size.height * 0.7305367, + ); + path5.moveTo(size.width * 0.3053666, size.height * 0.6043084); + path5.cubicTo( + size.width * 0.2978080, + size.height * 0.6356765, + size.width * 0.2928949, + size.height * 0.6972789, + size.width * 0.2751323, + size.height * 0.7244898, + ); + path5.moveTo(size.width * 0.2974301, size.height * 0.6621315); + path5.cubicTo( + size.width * 0.3004535, + size.height * 0.6734694, + size.width * 0.3034769, + size.height * 0.6851852, + size.width * 0.3087680, + size.height * 0.6961451, + ); + path5.moveTo(size.width * 0.3117914, size.height * 0.7040816); + path5.lineTo(size.width * 0.3136810, size.height * 0.7040816); + path5.moveTo(size.width * 0.3121693, size.height * 0.7112623); + path5.cubicTo( + size.width * 0.3182162, + size.height * 0.7120181, + size.width * 0.3219955, + size.height * 0.7093726, + size.width * 0.3280423, + size.height * 0.7082389, + ); + path5.moveTo(size.width * 0.3185941, size.height * 0.6224490); + path5.cubicTo( + size.width * 0.3201058, + size.height * 0.6269841, + size.width * 0.3204837, + size.height * 0.6318972, + size.width * 0.3216175, + size.height * 0.6364324, + ); + path5.cubicTo( + size.width * 0.3253968, + size.height * 0.6523054, + size.width * 0.3284203, + size.height * 0.6678005, + size.width * 0.3306878, + size.height * 0.6836735, + ); + path5.lineTo(size.width * 0.3321995, size.height * 0.7014361); + + final Paint paint5Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint5Stroke.color = contourColor.withOpacity(1); + paint5Stroke.strokeCap = StrokeCap.round; + paint5Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path5, paint5Stroke); + + final Path path6 = Path(); + path6.moveTo(size.width * 0.2362056, size.height * 0.5933485); + path6.cubicTo( + size.width * 0.2467876, + size.height * 0.6050642, + size.width * 0.2675737, + size.height * 0.6073318, + size.width * 0.2815571, + size.height * 0.6009070, + ); + path6.moveTo(size.width * 0.2165533, size.height * 0.5899471); + path6.cubicTo( + size.width * 0.2392290, + size.height * 0.5967498, + size.width * 0.2543462, + size.height * 0.5793651, + size.width * 0.2641723, + size.height * 0.5612245, + ); + path6.moveTo(size.width * 0.2033258, size.height * 0.5835223); + path6.cubicTo( + size.width * 0.2071051, + size.height * 0.5884354, + size.width * 0.2120181, + size.height * 0.5891912, + size.width * 0.2169312, + size.height * 0.5861678, + ); + path6.moveTo(size.width * 0.1965231, size.height * 0.5529101); + path6.cubicTo( + size.width * 0.1965231, + size.height * 0.5551776, + size.width * 0.1840514, + size.height * 0.5680272, + size.width * 0.1870748, + size.height * 0.5774754, + ); + path6.moveTo(size.width * 0.1987906, size.height * 0.5234316); + path6.cubicTo( + size.width * 0.1987906, + size.height * 0.5287226, + size.width * 0.2037037, + size.height * 0.5415722, + size.width * 0.2089947, + size.height * 0.5479970, + ); + path6.moveTo(size.width * 0.2256236, size.height * 0.5245654); + path6.arcToPoint( + Offset(size.width * 0.2354497, size.height * 0.5483749), + radius: Radius.elliptical( + size.width * 0.05668934, + size.height * 0.05668934, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path6.moveTo(size.width * 0.1904762, size.height * 0.4947090); + path6.cubicTo( + size.width * 0.1764928, + size.height * 0.5136054, + size.width * 0.1836735, + size.height * 0.5393046, + size.width * 0.1965231, + size.height * 0.5521542, + ); + + final Paint paint6Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint6Stroke.color = contourColor.withOpacity(1); + paint6Stroke.strokeCap = StrokeCap.round; + paint6Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path6, paint6Stroke); + + final Path path7 = Path(); + path7.moveTo(size.width * 0.09826153, size.height * 0.4595616); + path7.cubicTo( + size.width * 0.1046863, + size.height * 0.4935752, + size.width * 0.1337868, + size.height * 0.5117158, + size.width * 0.1825397, + size.height * 0.5124717, + ); + + final Paint paint7Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint7Stroke.color = contourColor.withOpacity(1); + paint7Stroke.strokeCap = StrokeCap.round; + paint7Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path7, paint7Stroke); + + final Path path8 = Path(); + path8.moveTo(size.width * 0.09788360, size.height * 0.4546485); + path8.cubicTo( + size.width * 0.09297052, + size.height * 0.4421769, + size.width * 0.1092215, + size.height * 0.4334845, + size.width * 0.1152683, + size.height * 0.4527589, + ); + path8.cubicTo( + size.width * 0.1182918, + size.height * 0.4625850, + size.width * 0.1228269, + size.height * 0.4724112, + size.width * 0.1269841, + size.height * 0.4788360, + ); + path8.moveTo(size.width * 0.1292517, size.height * 0.4811036); + path8.cubicTo( + size.width * 0.1341648, + size.height * 0.4845049, + size.width * 0.1398337, + size.height * 0.4863946, + size.width * 0.1447468, + size.height * 0.4886621, + ); + path8.moveTo(size.width * 0.1462585, size.height * 0.4894180); + path8.cubicTo( + size.width * 0.1424792, + size.height * 0.4818594, + size.width * 0.1371882, + size.height * 0.4701436, + size.width * 0.1352986, + size.height * 0.4622071, + ); + path8.cubicTo( + size.width * 0.1334089, + size.height * 0.4531368, + size.width * 0.1451247, + size.height * 0.4459562, + size.width * 0.1504157, + size.height * 0.4584278, + ); + path8.moveTo(size.width * 0.1670446, size.height * 0.4935752); + path8.cubicTo( + size.width * 0.1632653, + size.height * 0.4826153, + size.width * 0.1557067, + size.height * 0.4678760, + size.width * 0.1507937, + size.height * 0.4580499, + ); + + final Paint paint8Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint8Stroke.color = contourColor.withOpacity(1); + paint8Stroke.strokeCap = StrokeCap.round; + paint8Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path8, paint8Stroke); + + final Path path9 = Path(); + path9.moveTo(size.width * 0.1957672, size.height * 0.4950869); + path9.cubicTo( + size.width * 0.1719577, + size.height * 0.4977324, + size.width * 0.1938776, + size.height * 0.4818594, + size.width * 0.2071051, + size.height * 0.4829932, + ); + path9.cubicTo( + size.width * 0.2021920, + size.height * 0.4818594, + size.width * 0.1882086, + size.height * 0.4829932, + size.width * 0.1851852, + size.height * 0.4773243, + ); + path9.cubicTo( + size.width * 0.1814059, + size.height * 0.4697657, + size.width * 0.2116402, + size.height * 0.4671202, + size.width * 0.2161754, + size.height * 0.4663643, + ); + path9.cubicTo( + size.width * 0.2422525, + size.height * 0.4629630, + size.width * 0.2630385, + size.height * 0.4754346, + size.width * 0.2690854, + size.height * 0.4905518, + ); + + final Paint paint9Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint9Stroke.color = contourColor.withOpacity(1); + paint9Stroke.strokeCap = StrokeCap.round; + paint9Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path9, paint9Stroke); + + final Path path10 = Path(); + path10.moveTo(size.width * 0.2694633, size.height * 0.4935752); + path10.cubicTo( + size.width * 0.2872260, + size.height * 0.4897959, + size.width * 0.2989418, + size.height * 0.4860166, + size.width * 0.3163265, + size.height * 0.4799698, + ); + path10.moveTo(size.width * 0.2751323, size.height * 0.5105820); + path10.cubicTo( + size.width * 0.2970522, + size.height * 0.5041572, + size.width * 0.3817082, + size.height * 0.4863946, + size.width * 0.3809524, + size.height * 0.4538927, + ); + path10.moveTo(size.width * 0.3790627, size.height * 0.4459562); + path10.cubicTo( + size.width * 0.3809524, + size.height * 0.4444444, + size.width * 0.3805745, + size.height * 0.4452003, + size.width * 0.3820862, + size.height * 0.4433107, + ); + path10.moveTo(size.width * 0.3193500, size.height * 0.4773243); + path10.cubicTo( + size.width * 0.3163265, + size.height * 0.4705215, + size.width * 0.3163265, + size.height * 0.4629630, + size.width * 0.3129252, + size.height * 0.4561602, + ); + path10.moveTo(size.width * 0.3401361, size.height * 0.4705215); + path10.cubicTo( + size.width * 0.3469388, + size.height * 0.4671202, + size.width * 0.3590325, + size.height * 0.4606954, + size.width * 0.3578987, + size.height * 0.4489796, + ); + path10.moveTo(size.width * 0.3371126, size.height * 0.4693878); + path10.cubicTo( + size.width * 0.3333333, + size.height * 0.4603175, + size.width * 0.3276644, + size.height * 0.4327286, + size.width * 0.3163265, + size.height * 0.4399093, + ); + path10.cubicTo( + size.width * 0.3106576, + size.height * 0.4433107, + size.width * 0.3110355, + size.height * 0.4478458, + size.width * 0.3117914, + size.height * 0.4531368, + ); + path10.moveTo(size.width * 0.4100529, size.height * 0.7093726); + path10.cubicTo( + size.width * 0.4149660, + size.height * 0.7105064, + size.width * 0.4229025, + size.height * 0.7093726, + size.width * 0.4244142, + size.height * 0.7082389, + ); + path10.moveTo(size.width * 0.4327286, size.height * 0.7048375); + path10.lineTo(size.width * 0.4289494, size.height * 0.7010582); + path10.moveTo(size.width * 0.4108088, size.height * 0.7010582); + path10.cubicTo( + size.width * 0.4092971, + size.height * 0.6708239, + size.width * 0.4115646, + size.height * 0.6405896, + size.width * 0.4108088, + size.height * 0.6103553, + ); + path10.moveTo(size.width * 0.4357521, size.height * 0.6965231); + path10.cubicTo( + size.width * 0.4410431, + size.height * 0.6560847, + size.width * 0.4508692, + size.height * 0.6141345, + size.width * 0.4527589, + size.height * 0.5729403, + ); + path10.moveTo(size.width * 0.4508692, size.height * 0.5672714); + path10.cubicTo( + size.width * 0.4546485, + size.height * 0.5702948, + size.width * 0.4523810, + size.height * 0.5680272, + size.width * 0.4569161, + size.height * 0.5748299, + ); + path10.moveTo(size.width * 0.4656085, size.height * 0.6855631); + path10.lineTo(size.width * 0.4693878, size.height * 0.6817838); + + final Paint paint10Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint10Stroke.color = contourColor.withOpacity(1); + paint10Stroke.strokeCap = StrokeCap.round; + paint10Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path10, paint10Stroke); + + final Path path11 = Path(); + path11.moveTo(size.width * 0.4648526, size.height * 0.6753590); + path11.cubicTo( + size.width * 0.4603175, + size.height * 0.6579743, + size.width * 0.4520030, + size.height * 0.6417234, + size.width * 0.4452003, + size.height * 0.6254724, + ); + path11.moveTo(size.width * 0.4739229, size.height * 0.6878307); + path11.arcToPoint( + Offset(size.width * 0.4863946, size.height * 0.6832955), + radius: Radius.elliptical( + size.width * 0.04913076, + size.height * 0.04913076, + ), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path11.moveTo(size.width * 0.4882842, size.height * 0.6746032); + path11.arcToPoint( + Offset(size.width * 0.4606954, size.height * 0.5362812), + radius: + Radius.elliptical(size.width * 0.8752834, size.height * 0.8752834), + rotation: 0, + largeArc: false, + clockwise: false, + ); + path11.moveTo(size.width * 0.4622071, size.height * 0.5328798); + path11.cubicTo( + size.width * 0.4863946, + size.height * 0.5166289, + size.width * 0.4735450, + size.height * 0.4822373, + size.width * 0.4546485, + size.height * 0.4686319, + ); + + final Paint paint11Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint11Stroke.color = contourColor.withOpacity(1); + paint11Stroke.strokeCap = StrokeCap.round; + paint11Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path11, paint11Stroke); + + final Path path12 = Path(); + path12.moveTo(size.width * 0.4512472, size.height * 0.4761905); + path12.cubicTo( + size.width * 0.4531368, + size.height * 0.4803477, + size.width * 0.4572940, + size.height * 0.4863946, + size.width * 0.4588057, + size.height * 0.4894180, + ); + path12.moveTo(size.width * 0.4501134, size.height * 0.4829932); + path12.cubicTo( + size.width * 0.4425548, + size.height * 0.4913076, + size.width * 0.4399093, + size.height * 0.5113379, + size.width * 0.4512472, + size.height * 0.5173847, + ); + path12.moveTo(size.width * 0.3900227, size.height * 0.5000000); + path12.cubicTo( + size.width * 0.4070295, + size.height * 0.5011338, + size.width * 0.4270597, + size.height * 0.5022676, + size.width * 0.4433107, + size.height * 0.5083144, + ); + + final Paint paint12Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint12Stroke.color = contourColor.withOpacity(1); + paint12Stroke.strokeCap = StrokeCap.round; + paint12Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path12, paint12Stroke); + + final Path path13 = Path(); + path13.moveTo(size.width * 0.3065004, size.height * 0.6084656); + path13.cubicTo( + size.width * 0.3072562, + size.height * 0.6133787, + size.width * 0.3091459, + size.height * 0.6179138, + size.width * 0.3140590, + size.height * 0.6194255, + ); + path13.cubicTo( + size.width * 0.3201058, + size.height * 0.6224490, + size.width * 0.3941799, + size.height * 0.6130008, + size.width * 0.4160998, + size.height * 0.6069539, + ); + path13.moveTo(size.width * 0.4225246, size.height * 0.5990174); + path13.cubicTo( + size.width * 0.4213908, + size.height * 0.5975057, + size.width * 0.4202570, + size.height * 0.5959940, + size.width * 0.4187453, + size.height * 0.5952381, + ); + path13.moveTo(size.width * 0.4270597, size.height * 0.5910809); + path13.cubicTo( + size.width * 0.4270597, + size.height * 0.5850340, + size.width * 0.4198791, + size.height * 0.5393046, + size.width * 0.4195011, + size.height * 0.5328798, + ); + path13.cubicTo( + size.width * 0.4183673, + size.height * 0.5234316, + size.width * 0.4157218, + size.height * 0.5158730, + size.width * 0.4032502, + size.height * 0.5177627, + ); + path13.moveTo(size.width * 0.3926682, size.height * 0.5721844); + path13.cubicTo( + size.width * 0.3990930, + size.height * 0.5767196, + size.width * 0.4092971, + size.height * 0.5831444, + size.width * 0.4138322, + size.height * 0.5884354, + ); + + final Paint paint13Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint13Stroke.color = contourColor.withOpacity(1); + paint13Stroke.strokeCap = StrokeCap.round; + paint13Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path13, paint13Stroke); + + final Path path14 = Path(); + path14.moveTo(size.width * 0.4104308, size.height * 0.5226757); + path14.cubicTo( + size.width * 0.3998488, + size.height * 0.5377929, + size.width * 0.3847317, + size.height * 0.5740741, + size.width * 0.3707483, + size.height * 0.5755858, + ); + path14.cubicTo( + size.width * 0.3556311, + size.height * 0.5767196, + size.width * 0.3163265, + size.height * 0.5468632, + size.width * 0.3038549, + size.height * 0.5389267, + ); + path14.moveTo(size.width * 0.3182162, size.height * 0.6111111); + path14.cubicTo( + size.width * 0.3235072, + size.height * 0.6027967, + size.width * 0.3306878, + size.height * 0.5963719, + size.width * 0.3356009, + size.height * 0.5876795, + ); + path14.moveTo(size.width * 0.3408919, size.height * 0.5801209); + path14.cubicTo( + size.width * 0.3431595, + size.height * 0.5767196, + size.width * 0.3454271, + size.height * 0.5729403, + size.width * 0.3469388, + size.height * 0.5687831, + ); + + final Paint paint14Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint14Stroke.color = contourColor.withOpacity(1); + paint14Stroke.strokeCap = StrokeCap.round; + paint14Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path14, paint14Stroke); + + final Path path15 = Path(); + path15.moveTo(size.width * 0.3046107, size.height * 0.6009070); + path15.cubicTo( + size.width * 0.3034769, + size.height * 0.5903250, + size.width * 0.2955404, + size.height * 0.5529101, + size.width * 0.2955404, + size.height * 0.5427060, + ); + path15.cubicTo( + size.width * 0.2955404, + size.height * 0.5328798, + size.width * 0.2978080, + size.height * 0.5275888, + size.width * 0.3219955, + size.height * 0.5264550, + ); + path15.moveTo(size.width * 0.3303099, size.height * 0.5253212); + path15.cubicTo( + size.width * 0.3514739, + size.height * 0.5215420, + size.width * 0.3733938, + size.height * 0.5196523, + size.width * 0.3934240, + size.height * 0.5188964, + ); + path15.moveTo(size.width * 0.3518519, size.height * 0.4935752); + path15.cubicTo( + size.width * 0.3662132, + size.height * 0.4860166, + size.width * 0.3749055, + size.height * 0.5079365, + size.width * 0.3756614, + size.height * 0.5166289, + ); + path15.moveTo(size.width * 0.3631897, size.height * 0.4818594); + path15.cubicTo( + size.width * 0.3813303, + size.height * 0.4829932, + size.width * 0.3907785, + size.height * 0.5034014, + size.width * 0.3896447, + size.height * 0.5170068, + ); + + final Paint paint15Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint15Stroke.color = contourColor.withOpacity(1); + paint15Stroke.strokeCap = StrokeCap.round; + paint15Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path15, paint15Stroke); + + final Path path16 = Path(); + path16.moveTo(size.width * 0.3049887, size.height * 0.5291005); + path16.cubicTo( + size.width * 0.3034769, + size.height * 0.5222978, + size.width * 0.3004535, + size.height * 0.5154951, + size.width * 0.2981859, + size.height * 0.5086924, + ); + path16.moveTo(size.width * 0.3212396, size.height * 0.5268330); + path16.cubicTo( + size.width * 0.3185941, + size.height * 0.5192744, + size.width * 0.3167045, + size.height * 0.5117158, + size.width * 0.3129252, + size.height * 0.5049131, + ); + path16.moveTo(size.width * 0.1678005, size.height * 0.4950869); + path16.lineTo(size.width * 0.1749811, size.height * 0.4965986); + path16.moveTo(size.width * 0.2683296, size.height * 0.5226757); + path16.cubicTo( + size.width * 0.2910053, + size.height * 0.5464853, + size.width * 0.2944067, + size.height * 0.5162509, + size.width * 0.2728647, + size.height * 0.5102041, + ); + + final Paint paint16Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint16Stroke.color = contourColor.withOpacity(1); + paint16Stroke.strokeCap = StrokeCap.round; + paint16Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path16, paint16Stroke); + + final Path path17 = Path(); + path17.moveTo(size.width * 0.1927438, size.height * 0.5820106); + path17.cubicTo( + size.width * 0.1980348, + size.height * 0.5839002, + size.width * 0.2033258, + size.height * 0.5823885, + size.width * 0.2101285, + size.height * 0.5782313, + ); + + final Paint paint17Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint17Stroke.color = contourColor.withOpacity(1); + paint17Stroke.strokeCap = StrokeCap.round; + paint17Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path17, paint17Stroke); + + final Paint paint17Fill = Paint()..style = PaintingStyle.fill; + paint17Fill.color = contourColor.withOpacity(1); + canvas.drawPath(path17, paint17Fill); + + final Path path18 = Path(); + path18.moveTo(size.width * 0.3764172, size.height * 0.4365079); + path18.cubicTo( + size.width * 0.3730159, + size.height * 0.4270597, + size.width * 0.3718821, + size.height * 0.4040060, + size.width * 0.3571429, + size.height * 0.4085412, + ); + path18.cubicTo( + size.width * 0.3469388, + size.height * 0.4119426, + size.width * 0.3563870, + size.height * 0.4349962, + size.width * 0.3571429, + size.height * 0.4402872, + ); + + final Paint paint18Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint18Stroke.color = contourColor.withOpacity(1); + paint18Stroke.strokeCap = StrokeCap.round; + paint18Stroke.strokeJoin = StrokeJoin.miter; + canvas.drawPath(path18, paint18Stroke); + + final Path path19 = Path(); + path19.moveTo(size.width * 0.1530612, size.height * 0.4104308); + path19.cubicTo( + size.width * 0.1477702, + size.height * 0.4085412, + size.width * 0.1447468, + size.height * 0.4028723, + size.width * 0.1455026, + size.height * 0.3972033, + ); + path19.cubicTo( + size.width * 0.1458806, + size.height * 0.3919123, + size.width * 0.1485261, + size.height * 0.3866213, + size.width * 0.1530612, + size.height * 0.3839758, + ); + path19.cubicTo( + size.width * 0.1568405, + size.height * 0.3817082, + size.width * 0.1617536, + size.height * 0.3809524, + size.width * 0.1655329, + size.height * 0.3828420, + ); + path19.cubicTo( + size.width * 0.1700680, + size.height * 0.3847317, + size.width * 0.1742252, + size.height * 0.3881330, + size.width * 0.1757370, + size.height * 0.3926682, + ); + path19.arcToPoint( + Offset(size.width * 0.1734694, size.height * 0.4096750), + radius: Radius.elliptical( + size.width * 0.01889645, + size.height * 0.01889645, + ), + rotation: 0, + largeArc: false, + clockwise: true, + ); + path19.cubicTo( + size.width * 0.1712018, + size.height * 0.4134543, + size.width * 0.1659108, + size.height * 0.4142101, + size.width * 0.1651550, + size.height * 0.4187453, + ); + path19.cubicTo( + size.width * 0.1643991, + size.height * 0.4232804, + size.width * 0.1689342, + size.height * 0.4270597, + size.width * 0.1708239, + size.height * 0.4308390, + ); + path19.moveTo(size.width * 0.1757370, size.height * 0.4383976); + path19.cubicTo( + size.width * 0.1757370, + size.height * 0.4387755, + size.width * 0.1761149, + size.height * 0.4383976, + size.width * 0.1761149, + size.height * 0.4383976, + ); + path19.lineTo(size.width * 0.1761149, size.height * 0.4387755); + + final Paint paint19Stroke = Paint() + ..style = PaintingStyle.stroke + ..strokeWidth = size.width * 0.007558579; + paint19Stroke.color = contourColor.withOpacity(1); + paint19Stroke.strokeCap = StrokeCap.round; + paint19Stroke.strokeJoin = StrokeJoin.round; + canvas.drawPath(path19, paint19Stroke); + } + + @override + bool shouldRepaint(covariant final StrayDeerPainter oldDelegate) => + colorPalette != oldDelegate.colorPalette; +} diff --git a/lib/logic/api_maps/rest_maps/backblaze.dart b/lib/logic/api_maps/rest_maps/backblaze.dart index edc283b5..8ea94803 100644 --- a/lib/logic/api_maps/rest_maps/backblaze.dart +++ b/lib/logic/api_maps/rest_maps/backblaze.dart @@ -90,7 +90,8 @@ class BackblazeApi extends ApiMap { ), ); if (response.statusCode == HttpStatus.ok) { - isTokenValid = response.data['allowed']['capabilities'].contains('listBuckets'); + isTokenValid = + response.data['allowed']['capabilities'].contains('listBuckets'); } else if (response.statusCode == HttpStatus.unauthorized) { isTokenValid = false; } else { diff --git a/lib/logic/cubit/app_settings/app_settings_cubit.dart b/lib/logic/cubit/app_settings/app_settings_cubit.dart index 06b46730..d013d418 100644 --- a/lib/logic/cubit/app_settings/app_settings_cubit.dart +++ b/lib/logic/cubit/app_settings/app_settings_cubit.dart @@ -1,7 +1,12 @@ +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:hive/hive.dart'; +import 'package:material_color_utilities/material_color_utilities.dart' + as color_utils; +import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/hive_config.dart'; +import 'package:selfprivacy/theming/factory/app_theme_factory.dart'; export 'package:provider/provider.dart'; @@ -20,7 +25,7 @@ class AppSettingsCubit extends Cubit { Box box = Hive.box(BNames.appSettingsBox); - void load() { + void load() async { final bool? isDarkModeOn = box.get(BNames.isDarkModeOn); final bool? isOnboardingShowing = box.get(BNames.isOnboardingShowing); emit( @@ -29,6 +34,14 @@ class AppSettingsCubit extends Cubit { isOnboardingShowing: isOnboardingShowing, ), ); + WidgetsFlutterBinding.ensureInitialized(); + final color_utils.CorePalette? colorPalette = + await AppThemeFactory.getCorePalette(); + emit( + state.copyWith( + corePalette: colorPalette, + ), + ); } void updateDarkMode({required final bool isDarkModeOn}) { diff --git a/lib/logic/cubit/app_settings/app_settings_state.dart b/lib/logic/cubit/app_settings/app_settings_state.dart index 92da9667..8b29f6e9 100644 --- a/lib/logic/cubit/app_settings/app_settings_state.dart +++ b/lib/logic/cubit/app_settings/app_settings_state.dart @@ -4,20 +4,27 @@ class AppSettingsState extends Equatable { const AppSettingsState({ required this.isDarkModeOn, required this.isOnboardingShowing, + this.corePalette, }); final bool isDarkModeOn; final bool isOnboardingShowing; + final color_utils.CorePalette? corePalette; AppSettingsState copyWith({ final bool? isDarkModeOn, final bool? isOnboardingShowing, + final color_utils.CorePalette? corePalette, }) => AppSettingsState( isDarkModeOn: isDarkModeOn ?? this.isDarkModeOn, isOnboardingShowing: isOnboardingShowing ?? this.isOnboardingShowing, + corePalette: corePalette ?? this.corePalette, ); + color_utils.CorePalette get corePaletteOrDefault => + corePalette ?? color_utils.CorePalette.of(BrandColors.primary.value); + @override - List get props => [isDarkModeOn, isOnboardingShowing]; + List get props => [isDarkModeOn, isOnboardingShowing, corePalette]; } diff --git a/lib/logic/get_it/console.dart b/lib/logic/get_it/console.dart index 290f31ab..a523c5e8 100644 --- a/lib/logic/get_it/console.dart +++ b/lib/logic/get_it/console.dart @@ -9,5 +9,9 @@ class ConsoleModel extends ChangeNotifier { void addMessage(final Message message) { messages.add(message); notifyListeners(); + // Make sure we don't have too many messages + if (messages.length > 500) { + messages.removeAt(0); + } } } diff --git a/lib/logic/models/hive/server_details.dart b/lib/logic/models/hive/server_details.dart index 57a54762..54ec257f 100644 --- a/lib/logic/models/hive/server_details.dart +++ b/lib/logic/models/hive/server_details.dart @@ -95,4 +95,15 @@ enum ServerProvider { return unknown; } } + + String get displayName { + switch (this) { + case ServerProvider.hetzner: + return 'Hetzner Cloud'; + case ServerProvider.digitalOcean: + return 'Digital Ocean'; + default: + return 'Unknown'; + } + } } diff --git a/lib/logic/models/service.dart b/lib/logic/models/service.dart index 898d2965..039065e3 100644 --- a/lib/logic/models/service.dart +++ b/lib/logic/models/service.dart @@ -105,13 +105,13 @@ class ServiceStorageUsage { } enum ServiceStatus { + failed, + reloading, activating, active, deactivating, - failed, inactive, - off, - reloading; + off; factory ServiceStatus.fromGraphQL(final Enum$ServiceStatusEnum graphQL) { switch (graphQL) { diff --git a/lib/theming/factory/app_theme_factory.dart b/lib/theming/factory/app_theme_factory.dart index 65bb1648..e3ce278a 100644 --- a/lib/theming/factory/app_theme_factory.dart +++ b/lib/theming/factory/app_theme_factory.dart @@ -1,10 +1,7 @@ -import 'dart:io'; - import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:system_theme/system_theme.dart'; -import 'package:gtk_theme_fl/gtk_theme_fl.dart'; +import 'package:material_color_utilities/palettes/core_palette.dart'; abstract class AppThemeFactory { AppThemeFactory._(); @@ -22,40 +19,17 @@ abstract class AppThemeFactory { required final Color fallbackColor, final bool isDark = false, }) async { - ColorScheme? gtkColorsScheme; final Brightness brightness = isDark ? Brightness.dark : Brightness.light; final ColorScheme? dynamicColorsScheme = await _getDynamicColors(brightness); - if (Platform.isLinux) { - final GtkThemeData themeData = await GtkThemeData.initialize(); - final bool isGtkDark = - Color(themeData.theme_bg_color).computeLuminance() < 0.5; - final bool isInverseNeeded = isGtkDark != isDark; - gtkColorsScheme = ColorScheme.fromSeed( - seedColor: Color(themeData.theme_selected_bg_color), - brightness: brightness, - background: isInverseNeeded ? null : Color(themeData.theme_bg_color), - surface: isInverseNeeded ? null : Color(themeData.theme_base_color), - ); - } - - final SystemAccentColor accentColor = SystemAccentColor(fallbackColor); - - try { - await accentColor.load(); - } on MissingPluginException catch (e) { - print('_createAppTheme: ${e.message}'); - } - final ColorScheme fallbackColorScheme = ColorScheme.fromSeed( - seedColor: accentColor.accent, + seedColor: fallbackColor, brightness: brightness, ); - final ColorScheme colorScheme = - dynamicColorsScheme ?? gtkColorsScheme ?? fallbackColorScheme; + final ColorScheme colorScheme = dynamicColorsScheme ?? fallbackColorScheme; final Typography appTypography = Typography.material2021(); @@ -80,4 +54,12 @@ abstract class AppThemeFactory { return Future.value(null); } } + + static Future getCorePalette() async { + try { + return await DynamicColorPlugin.getCorePalette(); + } on PlatformException { + return Future.value(null); + } + } } diff --git a/lib/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart b/lib/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart index 0f60ed09..d53b5ced 100644 --- a/lib/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart +++ b/lib/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart @@ -15,7 +15,7 @@ class BrandBottomSheet extends StatelessWidget { Widget build(final BuildContext context) { final double mainHeight = MediaQuery.of(context).size.height - MediaQuery.of(context).padding.top - - 100; + 300; late Widget innerWidget; if (isExpended) { innerWidget = Scaffold( @@ -29,31 +29,28 @@ class BrandBottomSheet extends StatelessWidget { child: IntrinsicHeight(child: child), ); } - return ConstrainedBox( - constraints: BoxConstraints(maxHeight: mainHeight + 4 + 6), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Center( - child: Container( - height: 4, - width: 30, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: BrandColors.gray4, - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Center( + child: Container( + height: 4, + width: 30, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: BrandColors.gray4, ), ), - const SizedBox(height: 6), - ClipRRect( - borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: mainHeight), - child: innerWidget, - ), + ), + const SizedBox(height: 6), + ClipRRect( + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), + child: ConstrainedBox( + constraints: BoxConstraints(maxHeight: mainHeight), + child: innerWidget, ), - ], - ), + ), + ], ); } } diff --git a/lib/ui/components/progress_bar/progress_bar.dart b/lib/ui/components/progress_bar/progress_bar.dart index eae4161d..00f1388e 100644 --- a/lib/ui/components/progress_bar/progress_bar.dart +++ b/lib/ui/components/progress_bar/progress_bar.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/text_themes.dart'; import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; -import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class ProgressBar extends StatefulWidget { const ProgressBar({ @@ -63,13 +62,6 @@ class _ProgressBarState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - BrandText.h2('Progress'), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: even, - ), - const SizedBox(height: 7), Container( alignment: Alignment.centerLeft, decoration: BoxDecoration( @@ -98,11 +90,6 @@ class _ProgressBarState extends State { ), ), ), - const SizedBox(height: 5), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: odd, - ), ], ); } diff --git a/lib/ui/pages/onboarding/onboarding.dart b/lib/ui/pages/onboarding/onboarding.dart index 36478a1c..c00b4f12 100644 --- a/lib/ui/pages/onboarding/onboarding.dart +++ b/lib/ui/pages/onboarding/onboarding.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; -import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -49,11 +48,16 @@ class _OnboardingPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 30), - BrandText.h2( + Text( 'onboarding.page1_title'.tr(), + style: Theme.of(context).textTheme.headlineSmall, ), - const SizedBox(height: 20), - BrandText.body2('onboarding.page1_text'.tr()), + const SizedBox(height: 16), + Text( + 'onboarding.page1_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 16), Flexible( child: Center( child: Image.asset( @@ -86,34 +90,49 @@ class _OnboardingPageState extends State { maxHeight: MediaQuery.of(context).size.height, ), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 30), - BrandText.h2('onboarding.page2_title'.tr()), - const SizedBox(height: 20), - BrandText.body2('onboarding.page2_text'.tr()), - const SizedBox(height: 20), - Center( - child: Image.asset( - _fileName( - context: context, - path: 'assets/images/onboarding', - fileExtention: 'png', - fileName: 'logos_line', - ), - ), + Text( + 'onboarding.page2_title'.tr(), + style: Theme.of(context).textTheme.headlineSmall, ), - Flexible( - child: Center( - child: Image.asset( - _fileName( - context: context, - path: 'assets/images/onboarding', - fileExtention: 'png', - fileName: 'onboarding2', - ), - ), - ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_server_provider_title'.tr(), + style: Theme.of(context).textTheme.titleLarge, + ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_server_provider_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_dns_provider_title'.tr(), + style: Theme.of(context).textTheme.titleLarge, + ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_dns_provider_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_backup_provider_title'.tr(), + style: Theme.of(context).textTheme.titleLarge, + ), + const SizedBox(height: 16), + Text( + 'onboarding.page2_backup_provider_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 16), BrandButton.rised( onPressed: () { context.read().turnOffOnboarding(); diff --git a/lib/ui/pages/server_details/charts/cpu_chart.dart b/lib/ui/pages/server_details/charts/cpu_chart.dart index 8c3ae9c7..2ec349a0 100644 --- a/lib/ui/pages/server_details/charts/cpu_chart.dart +++ b/lib/ui/pages/server_details/charts/cpu_chart.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart'; @@ -82,7 +84,10 @@ class CpuChart extends StatelessWidget { ), ], minY: 0, - maxY: 100, + // Maximal value of data by 100 step + maxY: + ((data.map((final e) => e.value).reduce(max) - 1) / 100).ceil() * + 100.0, minX: 0, titlesData: FlTitlesData( topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), diff --git a/lib/ui/pages/services/services.dart b/lib/ui/pages/services/services.dart index c4226250..fc00922b 100644 --- a/lib/ui/pages/services/services.dart +++ b/lib/ui/pages/services/services.dart @@ -1,17 +1,12 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; -import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; -import 'package:selfprivacy/logic/models/job.dart'; import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/state_types.dart'; import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; -import 'package:selfprivacy/ui/components/brand_switch/brand_switch.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; @@ -21,14 +16,6 @@ import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/ui_helpers.dart'; import 'package:url_launcher/url_launcher.dart'; -const switchableServices = [ - 'bitwarden', - 'nextcloud', - 'pleroma', - 'gitea', - 'ocserv', -]; - class ServicesPage extends StatefulWidget { const ServicesPage({super.key}); @@ -54,6 +41,10 @@ class _ServicesPageState extends State { final isReady = context.watch().state is ServerInstallationFinished; + final services = [...context.watch().state.services]; + services + .sort((final a, final b) => a.status.index.compareTo(b.status.index)); + return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(52), @@ -71,10 +62,7 @@ class _ServicesPageState extends State { BrandText.body1('basis.services_title'.tr()), const SizedBox(height: 24), if (!isReady) ...[const NotReadyCard(), const SizedBox(height: 24)], - ...context - .read() - .state - .services + ...services .map( (final service) => Padding( padding: const EdgeInsets.only( @@ -100,24 +88,28 @@ class _Card extends StatelessWidget { final isReady = context.watch().state is ServerInstallationFinished; - final serviceState = context.watch().state; - final jobsCubit = context.watch(); - final jobState = jobsCubit.state; - - final switchableService = switchableServices.contains(service.id); - final hasSwitchJob = switchableService && - jobState is JobsStateWithJobs && - jobState.clientJobList.any( - (final el) => el is ServiceToggleJob && el.id == service.id, - ); - - final isSwitchOn = isReady && - (!switchableServices.contains(service.id) || - serviceState.isEnableByType(service)); - final config = context.watch().state; final domainName = UiHelpers.getDomainName(config); + StateType getStatus(final ServiceStatus status) { + switch (status) { + case ServiceStatus.active: + return StateType.stable; + case ServiceStatus.activating: + return StateType.stable; + case ServiceStatus.deactivating: + return StateType.uninitialized; + case ServiceStatus.inactive: + return StateType.uninitialized; + case ServiceStatus.failed: + return StateType.error; + case ServiceStatus.off: + return StateType.uninitialized; + case ServiceStatus.reloading: + return StateType.stable; + } + } + return GestureDetector( onTap: isReady ? () => Navigator.of(context) @@ -130,8 +122,7 @@ class _Card extends StatelessWidget { Row( children: [ IconStatusMask( - status: - isSwitchOn ? StateType.stable : StateType.uninitialized, + status: getStatus(service.status), icon: SvgPicture.string( service.svgIcon, width: 30.0, @@ -139,33 +130,6 @@ class _Card extends StatelessWidget { color: Theme.of(context).colorScheme.onBackground, ), ), - if (isReady && switchableService) ...[ - const Spacer(), - Builder( - builder: (final context) { - late bool isActive; - if (hasSwitchJob) { - isActive = (jobState.clientJobList.firstWhere( - (final el) => - el is ServiceToggleJob && el.id == service.id, - ) as ServiceToggleJob) - .needToTurnOn; - } else { - isActive = serviceState.isEnableByType(service); - } - - return BrandSwitch( - value: isActive, - onChanged: (final value) => jobsCubit.addJob( - ServiceToggleJob( - service: service, - needToTurnOn: value, - ), - ), - ); - }, - ), - ] ], ), ClipRect( @@ -215,22 +179,6 @@ class _Card extends StatelessWidget { const SizedBox(height: 10), ], ), - if (hasSwitchJob) - Positioned( - bottom: 24, - left: 0, - right: 0, - child: BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 3, - sigmaY: 2, - ), - child: BrandText.h2( - 'jobs.run_jobs'.tr(), - textAlign: TextAlign.center, - ), - ), - ) ], ), ) diff --git a/lib/ui/pages/setup/initializing/initializing.dart b/lib/ui/pages/setup/initializing/initializing.dart index 1e3e7982..36ddb8e9 100644 --- a/lib/ui/pages/setup/initializing/initializing.dart +++ b/lib/ui/pages/setup/initializing/initializing.dart @@ -11,7 +11,6 @@ import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cu import 'package:selfprivacy/logic/cubit/forms/setup/initializing/root_user_form_cubit.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; -import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart'; @@ -56,88 +55,91 @@ class InitializingPage extends StatelessWidget { .pushReplacement(materialRoute(const RootPage())); } }, - child: SafeArea( - child: Scaffold( - body: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: paddingH15V0.copyWith(top: 10, bottom: 10), - child: cubit.state is ServerInstallationFinished - ? const SizedBox( - height: 80, - ) - : ProgressBar( - steps: const [ - 'Hosting', - 'Server Type', - 'CloudFlare', - 'Backblaze', - 'Domain', - 'User', - 'Server', - 'Installation', - ], - activeIndex: cubit.state.porgressBar, - ), + child: Scaffold( + appBar: AppBar( + actions: [ + if (cubit.state is ServerInstallationFinished) + IconButton( + icon: const Icon(Icons.check), + onPressed: () { + Navigator.of(context) + .pushReplacement(materialRoute(const RootPage())); + }, + ) + ], + bottom: PreferredSize( + preferredSize: const Size.fromHeight(28), + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: ProgressBar( + steps: const [ + 'Hosting', + 'Server Type', + 'CloudFlare', + 'Backblaze', + 'Domain', + 'User', + 'Server', + 'Installation', + ], + activeIndex: cubit.state.porgressBar, + ), + ), + ), + ), + body: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0.0), + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: actualInitializingPage, ), - if (cubit.state.porgressBar == - ServerSetupProgress.serverProviderFilled.index) - BrandText.h2( - 'initializing.choose_location_type'.tr(), - ), - _addCard( - AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - child: actualInitializingPage, - ), + ), + ConstrainedBox( + constraints: BoxConstraints( + minHeight: MediaQuery.of(context).size.height - + MediaQuery.of(context).padding.top - + MediaQuery.of(context).padding.bottom - + 566, ), - ConstrainedBox( - constraints: BoxConstraints( - minHeight: MediaQuery.of(context).size.height - - MediaQuery.of(context).padding.top - - MediaQuery.of(context).padding.bottom - - 566, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + alignment: Alignment.center, + child: BrandButton.text( + title: cubit.state is ServerInstallationFinished + ? 'basis.close'.tr() + : 'basis.later'.tr(), + onPressed: () { + Navigator.of(context).pushAndRemoveUntil( + materialRoute(const RootPage()), + (final predicate) => false, + ); + }, + ), + ), + if (cubit.state is ServerInstallationEmpty) Container( alignment: Alignment.center, child: BrandButton.text( - title: cubit.state is ServerInstallationFinished - ? 'basis.close'.tr() - : 'basis.later'.tr(), + title: 'basis.connect_to_existing'.tr(), onPressed: () { - Navigator.of(context).pushAndRemoveUntil( - materialRoute(const RootPage()), - (final predicate) => false, + Navigator.of(context).push( + materialRoute( + const RecoveryRouting(), + ), ); }, ), - ), - if (cubit.state is ServerInstallationFinished) - Container() - else - Container( - alignment: Alignment.center, - child: BrandButton.text( - title: 'basis.connect_to_existing'.tr(), - onPressed: () { - Navigator.of(context).push( - materialRoute( - const RecoveryRouting(), - ), - ); - }, - ), - ) - ], - ), + ) + ], ), - ], - ), + ), + ], ), ), ), @@ -189,15 +191,16 @@ class InitializingPage extends StatelessWidget { builder: (final context) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset( - 'assets/images/logos/cloudflare.png', - width: 150, + Text( + '${'initializing.connect_to_server_provider'.tr()}Cloudflare', + style: Theme.of(context).textTheme.headlineSmall, ), - const SizedBox(height: 10), - BrandText.h2('initializing.connect_cloudflare'.tr()), - const SizedBox(height: 10), - BrandText.body2('initializing.manage_domain_dns'.tr()), - const Spacer(), + const SizedBox(height: 16), + Text( + 'initializing.manage_domain_dns'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 32), CubitFormTextField( formFieldCubit: context.read().apiKey, textAlign: TextAlign.center, @@ -206,7 +209,7 @@ class InitializingPage extends StatelessWidget { hintText: 'initializing.cloudflare_api_token'.tr(), ), ), - const Spacer(), + const SizedBox(height: 32), BrandButton.rised( onPressed: () => context.read().trySubmit(), @@ -236,14 +239,11 @@ class InitializingPage extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset( - 'assets/images/logos/backblaze.png', - height: 50, + Text( + '${'initializing.connect_to_server_provider'.tr()}Backblaze', + style: Theme.of(context).textTheme.headlineSmall, ), - const SizedBox(height: 10), - BrandText.h2('initializing.connect_backblaze_storage'.tr()), - const SizedBox(height: 10), - const Spacer(), + const SizedBox(height: 32), CubitFormTextField( formFieldCubit: context.read().keyId, textAlign: TextAlign.center, @@ -252,7 +252,7 @@ class InitializingPage extends StatelessWidget { hintText: 'KeyID', ), ), - const Spacer(), + const SizedBox(height: 16), CubitFormTextField( formFieldCubit: context.read().applicationKey, @@ -262,7 +262,7 @@ class InitializingPage extends StatelessWidget { hintText: 'Master Application Key', ), ), - const Spacer(), + const SizedBox(height: 32), BrandButton.rised( onPressed: formCubitState.isSubmitting ? null @@ -292,91 +292,85 @@ class InitializingPage extends StatelessWidget { builder: (final context) { final DomainSetupState state = context.watch().state; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/logos/cloudflare.png', - width: 150, - ), - const SizedBox(height: 30), - BrandText.h2('basis.domain'.tr()), - const SizedBox(height: 10), - if (state is Empty) - BrandText.body2('initializing.no_connected_domains'.tr()), - if (state is Loading) - BrandText.body2( - state.type == LoadingTypes.loadingDomain - ? 'initializing.loading_domain_list'.tr() - : 'basis.saving'.tr(), + return SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'initializing.use_this_domain'.tr(), + style: Theme.of(context).textTheme.headlineSmall, ), - if (state is MoreThenOne) - BrandText.body2( - 'initializing.found_more_domains'.tr(), + const SizedBox(height: 16), + Text( + 'initializing.use_this_domain_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, ), - if (state is Loaded) ...[ - const SizedBox(height: 10), - Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: BrandText.h3( + const SizedBox(height: 32), + if (state is Empty) + Text( + 'initializing.no_connected_domains'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + if (state is Loading) + Text( + state.type == LoadingTypes.loadingDomain + ? 'initializing.loading_domain_list'.tr() + : 'basis.saving'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + if (state is MoreThenOne) + Text( + 'initializing.found_more_domains'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + if (state is Loaded) ...[ + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( state.domain, + style: Theme.of(context) + .textTheme + .headlineMedium + ?.copyWith( + color: + Theme.of(context).colorScheme.onBackground, + ), textAlign: TextAlign.center, ), - ), - SizedBox( - width: 56, - child: BrandButton.rised( - onPressed: () => - context.read().load(), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: const [ - Icon( - Icons.refresh, - color: Colors.white, - ), - ], - ), - ), - ), - ], - ) - ], - if (state is Empty) ...[ - const SizedBox(height: 30), - BrandButton.rised( - onPressed: () => context.read().load(), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.refresh, - color: Colors.white, - ), - const SizedBox(width: 10), - BrandText.buttonTitleText('domain.update_list'.tr()), ], ), - ), + ], + if (state is Empty) ...[ + const SizedBox(height: 30), + BrandButton.rised( + onPressed: () => context.read().load(), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.refresh, + color: Colors.white, + ), + const SizedBox(width: 10), + BrandText.buttonTitleText('domain.update_list'.tr()), + ], + ), + ), + ], + if (state is Loaded) ...[ + const SizedBox(height: 32), + BrandButton.rised( + onPressed: () => + context.read().saveDomain(), + text: 'initializing.save_domain'.tr(), + ), + ], ], - if (state is Loaded) ...[ - const SizedBox(height: 30), - BrandButton.rised( - onPressed: () => - context.read().saveDomain(), - text: 'initializing.save_domain'.tr(), - ), - ], - const SizedBox( - height: 10, - width: double.infinity, - ), - ], + ), ); }, ), @@ -393,12 +387,16 @@ class InitializingPage extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - BrandText.h2('initializing.create_master_account'.tr()), - const SizedBox(height: 10), - BrandText.body2( - 'initializing.enter_username_and_password'.tr(), + Text( + 'initializing.create_master_account'.tr(), + style: Theme.of(context).textTheme.headlineSmall, ), - const Spacer(), + const SizedBox(height: 16), + Text( + 'initializing.enter_username_and_password'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + if (formCubitState.isErrorShown) const SizedBox(height: 16), if (formCubitState.isErrorShown) Text( 'users.username_rule'.tr(), @@ -406,7 +404,7 @@ class InitializingPage extends StatelessWidget { color: Theme.of(context).colorScheme.error, ), ), - const SizedBox(height: 10), + const SizedBox(height: 32), CubitFormTextField( formFieldCubit: context.read().userName, textAlign: TextAlign.center, @@ -415,7 +413,7 @@ class InitializingPage extends StatelessWidget { hintText: 'basis.username'.tr(), ), ), - const SizedBox(height: 10), + const SizedBox(height: 16), BlocBuilder, FieldCubitState>( bloc: context.read().isVisible, builder: (final context, final state) { @@ -446,7 +444,7 @@ class InitializingPage extends StatelessWidget { ); }, ), - const Spacer(), + const SizedBox(height: 32), BrandButton.rised( onPressed: formCubitState.isSubmitting ? null @@ -466,11 +464,16 @@ class InitializingPage extends StatelessWidget { builder: (final context) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Spacer(flex: 2), - BrandText.h2('initializing.final'.tr()), - const SizedBox(height: 10), - BrandText.body2('initializing.create_server'.tr()), - const Spacer(), + Text( + 'initializing.final'.tr(), + style: Theme.of(context).textTheme.headlineSmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.create_server'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 128), BrandButton.rised( onPressed: isLoading ? null : appConfigCubit.createServerAndSetDnsRecords, @@ -505,55 +508,64 @@ class InitializingPage extends StatelessWidget { doneCount = 0; } return Builder( - builder: (final context) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 15), - BrandText.h4( - 'initializing.checks'.tr(args: [doneCount.toString(), '4']), - ), - const Spacer(flex: 2), - const SizedBox(height: 10), - BrandText.body2(text), - const SizedBox(height: 10), - if (doneCount == 0 && state.dnsMatches != null) - Column( - children: state.dnsMatches!.entries.map((final entry) { - final String domain = entry.key; - final bool isCorrect = entry.value; - return Row( - children: [ - if (isCorrect) const Icon(Icons.check, color: Colors.green), - if (!isCorrect) - const Icon(Icons.schedule, color: Colors.amber), - const SizedBox(width: 10), - Text(domain), - ], - ); - }).toList(), + builder: (final context) => SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'initializing.checks'.tr(args: [doneCount.toString(), '4']), + style: Theme.of(context).textTheme.headlineSmall, ), - const SizedBox(height: 10), - if (!state.isLoading) - Row( - children: [ - BrandText.body2('initializing.until_the_next_check'.tr()), - BrandTimer( - startDateTime: state.timerStart!, - duration: state.duration!, - ) - ], - ), - if (state.isLoading) BrandText.body2('initializing.check'.tr()), - ], + const SizedBox(height: 16), + if (text != null) + Text( + text, + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 128), + const SizedBox(height: 10), + if (doneCount == 0 && state.dnsMatches != null) + Column( + children: state.dnsMatches!.entries.map((final entry) { + final String domain = entry.key; + final bool isCorrect = entry.value; + return Row( + children: [ + if (isCorrect) + const Icon(Icons.check, color: Colors.green), + if (!isCorrect) + const Icon(Icons.schedule, color: Colors.amber), + const SizedBox(width: 10), + Text(domain), + ], + ); + }).toList(), + ), + const SizedBox(height: 10), + if (!state.isLoading) + Row( + children: [ + Text( + 'initializing.until_the_next_check'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + BrandTimer( + startDateTime: state.timerStart!, + duration: state.duration!, + ) + ], + ), + if (state.isLoading) + Text( + 'initializing.check'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), ), ); } - - Widget _addCard(final Widget child) => Container( - height: 450, - padding: paddingH15V0, - child: BrandCards.big(child: child), - ); } class _HowTo extends StatelessWidget { diff --git a/lib/ui/pages/setup/initializing/server_provider_picker.dart b/lib/ui/pages/setup/initializing/server_provider_picker.dart index 4934d1e3..bf99863b 100644 --- a/lib/ui/pages/setup/initializing/server_provider_picker.dart +++ b/lib/ui/pages/setup/initializing/server_provider_picker.dart @@ -1,13 +1,18 @@ import 'package:cubit_form/cubit_form.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart'; import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; +import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart'; +import 'package:selfprivacy/ui/components/brand_cards/outlined_card.dart'; import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; +import 'package:selfprivacy/ui/components/info_box/info_box.dart'; +import 'package:url_launcher/url_launcher.dart'; class ServerProviderPicker extends StatefulWidget { const ServerProviderPicker({ @@ -96,13 +101,16 @@ class ProviderInputDataPage extends StatelessWidget { Widget build(final BuildContext context) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - providerInfo.image, - const SizedBox(height: 10), Text( - 'initializing.connect_to_server'.tr(), - style: Theme.of(context).textTheme.titleLarge, + "${'initializing.connect_to_server_provider'.tr()}${providerInfo.providerType.displayName}", + style: Theme.of(context).textTheme.headlineSmall, ), - const Spacer(), + const SizedBox(height: 16), + Text( + 'initializing.connect_to_server_provider_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 32), CubitFormTextField( formFieldCubit: providerCubit.apiKey, textAlign: TextAlign.center, @@ -111,13 +119,13 @@ class ProviderInputDataPage extends StatelessWidget { hintText: 'Provider API Token', ), ), - const Spacer(), + const SizedBox(height: 32), FilledButton( title: 'basis.connect'.tr(), onPressed: () => providerCubit.trySubmit(), ), const SizedBox(height: 10), - OutlinedButton( + BrandOutlinedButton( child: Text('initializing.how'.tr()), onPressed: () => showModalBottomSheet( context: context, @@ -154,51 +162,189 @@ class ProviderSelectionPage extends StatelessWidget { final ServerInstallationCubit serverInstallationCubit; @override - Widget build(final BuildContext context) => Column( - children: [ - Text( - 'initializing.select_provider'.tr(), - style: Theme.of(context).textTheme.titleLarge, - ), - const SizedBox(height: 10), - Text( - 'initializing.place_where_data'.tr(), - ), - const SizedBox(height: 10), - ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 320, + Widget build(final BuildContext context) => SizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'initializing.connect_to_server'.tr(), + style: Theme.of(context).textTheme.headlineSmall, ), - child: Row( - children: [ - InkWell( - onTap: () { - serverInstallationCubit - .setServerProviderType(ServerProvider.hetzner); - callback(ServerProvider.hetzner); - }, - child: Image.asset( - 'assets/images/logos/hetzner.png', - width: 150, - ), - ), - const SizedBox( - width: 20, - ), - InkWell( - onTap: () { - serverInstallationCubit - .setServerProviderType(ServerProvider.digitalOcean); - callback(ServerProvider.digitalOcean); - }, - child: Image.asset( - 'assets/images/logos/digital_ocean.png', - width: 150, - ), - ), - ], + const SizedBox(height: 10), + Text( + 'initializing.select_provider'.tr(), + style: Theme.of(context).textTheme.bodyMedium, ), - ), - ], + const SizedBox(height: 10), + OutlinedCard( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 40, + height: 40, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + color: const Color(0xFFD50C2D), + ), + child: SvgPicture.asset( + 'assets/images/logos/hetzner.svg', + ), + ), + const SizedBox(width: 16), + Text( + 'Hetzner Cloud', + style: Theme.of(context).textTheme.titleMedium, + ), + ], + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_countries_title'.tr(), + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + 'initializing.select_provider_countries_text_hetzner' + .tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_price_title'.tr(), + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + 'initializing.select_provider_price_text_hetzner'.tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_payment_title'.tr(), + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + 'initializing.select_provider_payment_text_hetzner'.tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_email_notice'.tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + FilledButton( + title: 'basis.select'.tr(), + onPressed: () { + serverInstallationCubit + .setServerProviderType(ServerProvider.hetzner); + callback(ServerProvider.hetzner); + }, + ), + // Outlined button that will open website + BrandOutlinedButton( + onPressed: () => + _launchURL('https://www.hetzner.com/cloud'), + title: 'initializing.select_provider_site_button'.tr(), + ), + ], + ), + ), + ), + const SizedBox(height: 16), + OutlinedCard( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 40, + height: 40, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + color: const Color(0xFF0080FF), + ), + child: SvgPicture.asset( + 'assets/images/logos/digital_ocean.svg', + ), + ), + const SizedBox(width: 16), + Text( + 'Digital Ocean', + style: Theme.of(context).textTheme.titleMedium, + ), + ], + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_countries_title'.tr(), + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + 'initializing.select_provider_countries_text_do'.tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_price_title'.tr(), + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + 'initializing.select_provider_price_text_do'.tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.select_provider_payment_title'.tr(), + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + 'initializing.select_provider_payment_text_do'.tr(), + style: Theme.of(context).textTheme.bodySmall, + ), + const SizedBox(height: 16), + FilledButton( + title: 'basis.select'.tr(), + onPressed: () { + serverInstallationCubit + .setServerProviderType(ServerProvider.digitalOcean); + callback(ServerProvider.digitalOcean); + }, + ), + // Outlined button that will open website + BrandOutlinedButton( + onPressed: () => + _launchURL('https://www.digitalocean.com'), + title: 'initializing.select_provider_site_button'.tr(), + ), + ], + ), + ), + ), + const SizedBox(height: 16), + InfoBox(text: 'initializing.select_provider_notice'.tr()), + ], + ), ); } + +void _launchURL(final url) async { + try { + final Uri uri = Uri.parse(url); + await launchUrl( + uri, + mode: LaunchMode.externalApplication, + ); + } catch (e) { + print(e); + } +} diff --git a/lib/ui/pages/setup/initializing/server_type_picker.dart b/lib/ui/pages/setup/initializing/server_type_picker.dart index 04b3bd5f..5a6632c8 100644 --- a/lib/ui/pages/setup/initializing/server_type_picker.dart +++ b/lib/ui/pages/setup/initializing/server_type_picker.dart @@ -1,10 +1,12 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_theme.dart'; +import 'package:selfprivacy/illustrations/stray_deer.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; +import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/logic/models/server_provider_location.dart'; import 'package:selfprivacy/logic/models/server_type.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; +import 'package:selfprivacy/ui/components/info_box/info_box.dart'; class ServerTypePicker extends StatefulWidget { const ServerTypePicker({ @@ -68,27 +70,43 @@ class SelectLocationPage extends StatelessWidget { if ((snapshot.data as List).isEmpty) { return Text('initializing.no_locations_found'.tr()); } - return ListView( - padding: paddingH15V0, + return Column( children: [ + Text( + 'initializing.choose_location_type'.tr(), + style: Theme.of(context).textTheme.headlineSmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.choose_location_type_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 16), ...(snapshot.data! as List).map( - (final location) => InkWell( - onTap: () { - callback(location); - }, - child: Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (location.flag != null) Text(location.flag!), - const SizedBox(height: 8), - Text(location.title), - const SizedBox(height: 8), - if (location.description != null) - Text(location.description!), - ], + (final location) => SizedBox( + width: double.infinity, + child: InkWell( + onTap: () { + callback(location); + }, + child: Card( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${location.flag ?? ''} ${location.title}', + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 8), + if (location.description != null) + Text( + location.description!, + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), ), ), ), @@ -126,11 +144,33 @@ class SelectTypePage extends StatelessWidget { if (snapshot.hasData) { if ((snapshot.data as List).isEmpty) { return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'initializing.no_server_types_found'.tr(), + 'initializing.locations_not_found'.tr(), + style: Theme.of(context).textTheme.headlineSmall, ), - const SizedBox(height: 10), + const SizedBox(height: 16), + Text( + 'initializing.locations_not_found_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + LayoutBuilder( + builder: (final context, final constraints) => CustomPaint( + size: Size( + constraints.maxWidth, + (constraints.maxWidth * 1).toDouble(), + ), + painter: StrayDeerPainter( + colorScheme: Theme.of(context).colorScheme, + colorPalette: context + .read() + .state + .corePaletteOrDefault, + ), + ), + ), + const SizedBox(height: 16), BrandButton.rised( onPressed: () { backToLocationPickingCallback(); @@ -140,51 +180,120 @@ class SelectTypePage extends StatelessWidget { ], ); } - return ListView( - padding: paddingH15V0, + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text( + 'initializing.choose_server_type'.tr(), + style: Theme.of(context).textTheme.headlineSmall, + ), + const SizedBox(height: 16), + Text( + 'initializing.choose_server_type_text'.tr(), + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 16), ...(snapshot.data! as List).map( - (final type) => InkWell( - onTap: () { - serverInstallationCubit.setServerType(type); - }, - child: Card( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - type.title, - style: Theme.of(context).textTheme.bodyMedium, - ), - const SizedBox(height: 8), - Text( - 'cores: ${type.cores.toString()}', - style: Theme.of(context).textTheme.bodySmall, - ), - const SizedBox(height: 8), - Text( - 'ram: ${type.ram.toString()}', - style: Theme.of(context).textTheme.bodySmall, - ), - const SizedBox(height: 8), - Text( - 'disk: ${type.disk.gibibyte.toString()}', - style: Theme.of(context).textTheme.bodySmall, - ), - const SizedBox(height: 8), - Text( - 'price: ${type.price.value.toString()} ${type.price.currency}', - style: Theme.of(context).textTheme.bodySmall, - ), - ], + (final type) => SizedBox( + width: double.infinity, + child: InkWell( + onTap: () { + serverInstallationCubit.setServerType(type); + }, + child: Card( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + type.title, + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.memory_outlined, + color: + Theme.of(context).colorScheme.onSurface, + ), + const SizedBox(width: 8), + Text( + 'server.core_count'.plural(type.cores), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.memory_outlined, + color: + Theme.of(context).colorScheme.onSurface, + ), + const SizedBox(width: 8), + Text( + 'initializing.choose_server_type_ram' + .tr(args: [type.ram.toString()]), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.sd_card_outlined, + color: + Theme.of(context).colorScheme.onSurface, + ), + const SizedBox(width: 8), + Text( + 'initializing.choose_server_type_storage' + .tr( + args: [type.disk.gibibyte.toString()], + ), + style: + Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + const SizedBox(height: 8), + const Divider(height: 8), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.payments_outlined, + color: + Theme.of(context).colorScheme.onSurface, + ), + const SizedBox(width: 8), + Text( + 'initializing.choose_server_type_payment_per_month' + .tr( + args: [ + '${type.price.value.toString()} ${type.price.currency}' + ], + ), + style: + Theme.of(context).textTheme.bodyLarge, + ), + ], + ), + ], + ), ), ), ), ), ), - const SizedBox(height: 24), + const SizedBox(height: 16), + InfoBox(text: 'initializing.choose_server_type_notice'.tr()), ], ); } else { diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index cf327b12..075ecba3 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,17 +6,17 @@ #include "generated_plugin_registrant.h" +#include #include -#include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) dynamic_color_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); + dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); - g_autoptr(FlPluginRegistrar) gtk_theme_fl_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "GtkThemeFlPlugin"); - gtk_theme_fl_plugin_register_with_registrar(gtk_theme_fl_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 6c700a87..6fd458b2 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,8 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + dynamic_color flutter_secure_storage_linux - gtk_theme_fl url_launcher_linux ) diff --git a/pubspec.lock b/pubspec.lock index c5901997..cb43c377 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -308,7 +308,7 @@ packages: name: dynamic_color url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.5.4" easy_localization: dependency: "direct main" description: @@ -602,13 +602,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" - gtk_theme_fl: - dependency: "direct main" - description: - name: gtk_theme_fl - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.1" hive: dependency: "direct main" description: @@ -764,7 +757,7 @@ packages: source: hosted version: "0.12.12" material_color_utilities: - dependency: transitive + dependency: "direct main" description: name: material_color_utilities url: "https://pub.dartlang.org" @@ -1188,20 +1181,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" - system_theme: - dependency: "direct main" - description: - name: system_theme - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - system_theme_web: - dependency: transitive - description: - name: system_theme_web - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.2" term_glyph: dependency: transitive description: @@ -1414,4 +1393,4 @@ packages: version: "3.1.1" sdks: dart: ">=2.17.0 <3.0.0" - flutter: ">=3.0.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index af1521e1..d47daac7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: selfprivacy description: selfprivacy.org publish_to: 'none' -version: 0.7.0+16 +version: 0.8.0+17 environment: sdk: '>=2.17.0 <3.0.0' @@ -14,7 +14,7 @@ dependencies: cubit_form: ^2.0.1 device_info_plus: ^4.0.1 dio: ^4.0.4 - dynamic_color: ^1.4.0 + dynamic_color: ^1.5.4 easy_localization: ^3.0.0 either_option: ^2.0.1-dev.1 equatable: ^2.0.3 @@ -30,7 +30,6 @@ dependencies: graphql: ^5.1.1 graphql_codegen: ^0.10.2 graphql_flutter: ^5.1.0 - gtk_theme_fl: ^0.0.1 hive: ^2.2.3 hive_flutter: ^1.1.0 http: ^0.13.5 @@ -38,6 +37,7 @@ dependencies: ionicons: ^0.1.2 json_annotation: ^4.6.0 local_auth: ^2.0.2 + material_color_utilities: ^0.1.5 modal_bottom_sheet: ^2.0.1 nanoid: ^1.0.0 package_info: ^2.0.2 @@ -45,7 +45,6 @@ dependencies: provider: ^6.0.2 pub_semver: ^2.1.1 share_plus: ^4.0.4 - system_theme: ^2.0.0 timezone: ^0.8.0 url_launcher: ^6.0.20 wakelock: ^0.6.1+1 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 1feb1b08..9c422c29 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -9,7 +9,6 @@ #include #include #include -#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -19,8 +18,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); - SystemThemePluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("SystemThemePlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index fa5d72de..0039d570 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus_windows dynamic_color flutter_secure_storage_windows - system_theme url_launcher_windows )