From 5411a3051975f12f2c08f63a265dd3463b117040 Mon Sep 17 00:00:00 2001 From: Hiddify User Date: Fri, 26 Dec 2025 18:41:25 +0300 Subject: [PATCH] feat: Umbrix branding - logo and name changes - Changed app title from Hiddify to Umbrix in home page - Added custom Umbrix logo (192x192 PNG) - Updated intro page with Umbrix branding and gradient design - Updated drawer menu with Umbrix logo - Modified add profile modal with modern gradient cards - Updated Russian translations (appTitle: Umbrix) --- assets/translations/strings_ru.i18n.json | 2 +- .../common/adaptive_root_scaffold.dart | 14 +- lib/features/home/widget/home_page.dart | 2 +- lib/features/intro/widget/intro_page.dart | 304 +++++++++++++----- pubspec.yaml | 1 + 5 files changed, 241 insertions(+), 82 deletions(-) diff --git a/assets/translations/strings_ru.i18n.json b/assets/translations/strings_ru.i18n.json index 462c553c..d2fba1b5 100644 --- a/assets/translations/strings_ru.i18n.json +++ b/assets/translations/strings_ru.i18n.json @@ -1,6 +1,6 @@ { "general": { - "appTitle": "Hiddify", + "appTitle": "Umbrix", "reset": "Сброс", "toggle": { "enabled": "Включено", diff --git a/lib/features/common/adaptive_root_scaffold.dart b/lib/features/common/adaptive_root_scaffold.dart index 95a8d3a7..f5b2c4a9 100644 --- a/lib/features/common/adaptive_root_scaffold.dart +++ b/lib/features/common/adaptive_root_scaffold.dart @@ -1,6 +1,7 @@ import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; +import 'package:hiddify/gen/assets.gen.dart'; import 'package:hiddify/core/localization/translations.dart'; import 'package:hiddify/core/router/router.dart'; import 'package:hiddify/features/stats/widget/side_bar_stats_overview.dart'; @@ -123,16 +124,15 @@ class _CustomAdaptiveScaffold extends HookConsumerWidget { child: Column( children: [ Container( - width: 96, - height: 96, + width: 80, + height: 80, + padding: const EdgeInsets.all(12), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), + borderRadius: BorderRadius.circular(20), color: Theme.of(context).colorScheme.primaryContainer, ), - child: Icon( - Icons.shield_outlined, - size: 56, - color: Theme.of(context).colorScheme.primary, + child: Assets.images.umbrixLogo.image( + fit: BoxFit.contain, ), ), const SizedBox(height: 16), diff --git a/lib/features/home/widget/home_page.dart b/lib/features/home/widget/home_page.dart index 0968c0a1..ef59114d 100644 --- a/lib/features/home/widget/home_page.dart +++ b/lib/features/home/widget/home_page.dart @@ -36,7 +36,7 @@ class HomePage extends HookConsumerWidget { title: Text.rich( TextSpan( children: [ - TextSpan(text: t.general.appTitle), + const TextSpan(text: "Umbrix"), const TextSpan(text: " "), const WidgetSpan( child: AppVersionLabel(), diff --git a/lib/features/intro/widget/intro_page.dart b/lib/features/intro/widget/intro_page.dart index 7940109b..c6a79475 100644 --- a/lib/features/intro/widget/intro_page.dart +++ b/lib/features/intro/widget/intro_page.dart @@ -8,6 +8,7 @@ import 'package:hiddify/core/localization/locale_preferences.dart'; import 'package:hiddify/core/localization/translations.dart'; import 'package:hiddify/core/model/constants.dart'; import 'package:hiddify/core/model/region.dart'; +import 'package:hiddify/gen/assets.gen.dart'; import 'package:hiddify/core/preferences/general_preferences.dart'; import 'package:hiddify/features/common/general_pref_tiles.dart'; import 'package:hiddify/features/config_option/data/config_option_repository.dart'; @@ -25,7 +26,7 @@ class IntroPage extends HookConsumerWidget with PresLogger { @override Widget build(BuildContext context, WidgetRef ref) { final t = ref.watch(translationsProvider); - + final theme = Theme.of(context); final isStarting = useState(false); if (!locationInfoLoaded) { @@ -34,83 +35,214 @@ class IntroPage extends HookConsumerWidget with PresLogger { } return Scaffold( - body: SafeArea( - child: CustomScrollView( - shrinkWrap: true, - slivers: [ - SliverToBoxAdapter( - child: SizedBox( - width: 224, - height: 224, + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + theme.colorScheme.surface, + theme.colorScheme.surfaceContainerHighest, + ], + ), + ), + child: SafeArea( + child: CustomScrollView( + shrinkWrap: true, + slivers: [ + // Логотип и заголовок + SliverToBoxAdapter( child: Padding( - padding: const EdgeInsets.all(24), - child: Assets.images.logo.svg(), - ), - ), - ), - SliverCrossAxisConstrained( - maxCrossAxisExtent: 368, - child: MultiSliver( - children: [ - const LocalePrefTile(), - const SliverGap(4), - const RegionPrefTile(), - const SliverGap(4), - const EnableAnalyticsPrefTile(), - const SliverGap(4), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text.rich( - t.intro.termsAndPolicyCaution( - tap: (text) => TextSpan( - text: text, - style: const TextStyle(color: Colors.blue), - recognizer: TapGestureRecognizer() - ..onTap = () async { - await UriUtils.tryLaunch( - Uri.parse(Constants.termsAndConditionsUrl), - ); - }, + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + child: Column( + children: [ + // Логотип с анимацией + Hero( + tag: 'app_logo', + child: Container( + width: 120, + height: 120, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: theme.colorScheme.primaryContainer.withOpacity(0.3), + borderRadius: BorderRadius.circular(30), + boxShadow: [ + BoxShadow( + color: theme.colorScheme.primary.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: Assets.images.umbrixLogo.image( + fit: BoxFit.contain, + ), ), ), - style: Theme.of(context).textTheme.bodySmall, - ), + const Gap(24), + // Заголовок + Text( + 'Welcome to Umbrix', + style: theme.textTheme.headlineMedium?.copyWith( + fontWeight: FontWeight.bold, + color: theme.colorScheme.onSurface, + ), + textAlign: TextAlign.center, + ), + const Gap(8), + Text( + 'Fast and Secure', + style: theme.textTheme.bodyLarge?.copyWith( + color: theme.colorScheme.onSurfaceVariant, + ), + textAlign: TextAlign.center, + ), + ], ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 24, - ), - child: FilledButton( - onPressed: () async { - if (isStarting.value) return; - isStarting.value = true; - if (!ref.read(analyticsControllerProvider).requireValue) { - loggy.info("disabling analytics per user request"); - try { - await ref.read(analyticsControllerProvider.notifier).disableAnalytics(); - } catch (error, stackTrace) { - loggy.error( - "could not disable analytics", - error, - stackTrace, - ); - } - } - await ref.read(Preferences.introCompleted.notifier).update(true); - }, - child: isStarting.value - ? LinearProgressIndicator( - backgroundColor: Colors.transparent, - color: Theme.of(context).colorScheme.onSurface, - ) - : Text(t.intro.start), - ), - ), - ], + ), ), - ), - ], + + // Настройки в виде карточек + SliverCrossAxisConstrained( + maxCrossAxisExtent: 400, + child: MultiSliver( + children: [ + // Язык + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 6), + child: _SettingCard( + child: const LocalePrefTile(), + ), + ), + + // Регион + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 6), + child: _SettingCard( + child: const RegionPrefTile(), + ), + ), + + // Аналитика + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 6), + child: _SettingCard( + child: const EnableAnalyticsPrefTile(), + ), + ), + + const SliverGap(16), + + // Условия использования + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Text.rich( + t.intro.termsAndPolicyCaution( + tap: (text) => TextSpan( + text: text, + style: TextStyle( + color: theme.colorScheme.primary, + fontWeight: FontWeight.w600, + decoration: TextDecoration.underline, + ), + recognizer: TapGestureRecognizer() + ..onTap = () async { + await UriUtils.tryLaunch( + Uri.parse(Constants.termsAndConditionsUrl), + ); + }, + ), + ), + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.onSurfaceVariant, + ), + textAlign: TextAlign.center, + ), + ), + + // Кнопка начать + Padding( + padding: const EdgeInsets.fromLTRB(24, 24, 24, 32), + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + theme.colorScheme.primary, + theme.colorScheme.primary.withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: theme.colorScheme.primary.withOpacity(0.4), + blurRadius: 12, + offset: const Offset(0, 6), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: isStarting.value + ? null + : () async { + isStarting.value = true; + if (!ref.read(analyticsControllerProvider).requireValue) { + loggy.info("disabling analytics per user request"); + try { + await ref.read(analyticsControllerProvider.notifier).disableAnalytics(); + } catch (error, stackTrace) { + loggy.error( + "could not disable analytics", + error, + stackTrace, + ); + } + } + await ref.read(Preferences.introCompleted.notifier).update(true); + }, + borderRadius: BorderRadius.circular(16), + child: Container( + height: 56, + alignment: Alignment.center, + child: isStarting.value + ? SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator( + strokeWidth: 3, + valueColor: AlwaysStoppedAnimation( + theme.colorScheme.onPrimary, + ), + ), + ) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + t.intro.start, + style: theme.textTheme.titleMedium?.copyWith( + color: theme.colorScheme.onPrimary, + fontWeight: FontWeight.bold, + ), + ), + const Gap(8), + Icon( + Icons.arrow_forward_rounded, + color: theme.colorScheme.onPrimary, + ), + ], + ), + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), ), ), ); @@ -185,3 +317,29 @@ class RegionLocale { RegionLocale(this.region, this.locale); } + +// Карточка для настроек +class _SettingCard extends StatelessWidget { + const _SettingCard({required this.child}); + + final Widget child; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + decoration: BoxDecoration( + color: theme.colorScheme.surfaceContainerHighest.withOpacity(0.5), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: theme.colorScheme.outline.withOpacity(0.1), + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: child, + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 01806069..124dfb06 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -124,6 +124,7 @@ flutter: # - assets/core/geoip.db # - assets/core/geosite.db - assets/images/logo.svg + - assets/images/umbrix_logo.png - assets/images/tray_icon.ico - assets/images/tray_icon.png - assets/images/tray_icon_dark.ico