diff --git a/lib/config/bloc_config.dart b/lib/config/bloc_config.dart index d1ccd2f42f..373996e88d 100644 --- a/lib/config/bloc_config.dart +++ b/lib/config/bloc_config.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/users/users_cubit.dart'; @@ -10,8 +12,15 @@ class BlocAndProviderConfig extends StatelessWidget { @override Widget build(BuildContext context) { + var platformBrightness = + SchedulerBinding.instance.window.platformBrightness; + // var platformBrightness = Brightness.dark; return MultiProvider( providers: [ + BlocProvider( + create: (BuildContext context) => AppSettingsCubit( + isDarkModeOn: platformBrightness == Brightness.dark), + ), BlocProvider( create: (BuildContext context) => ServicesCubit(), ), diff --git a/lib/config/brand_colors.dart b/lib/config/brand_colors.dart index 25f5e70c1a..37309df4b7 100644 --- a/lib/config/brand_colors.dart +++ b/lib/config/brand_colors.dart @@ -41,7 +41,8 @@ class BrandColors { static const dividerColor = gray5; static const warning = red; - static get navBackground => white.withOpacity(0.8); + static get navBackgroundLight => white.withOpacity(0.8); + static get navBackgroundDark => black.withOpacity(0.8); static const List uninitializedGradientColors = [ Color(0xFF555555), diff --git a/lib/config/brand_theme.dart b/lib/config/brand_theme.dart index 954f7a6af8..9f5cfb00a7 100644 --- a/lib/config/brand_theme.dart +++ b/lib/config/brand_theme.dart @@ -4,7 +4,7 @@ import 'package:selfprivacy/config/text_themes.dart'; import 'brand_colors.dart'; -final theme = ThemeData( +final ligtTheme = ThemeData( primaryColor: BrandColors.primary, brightness: Brightness.light, scaffoldBackgroundColor: BrandColors.scaffoldBackground, @@ -24,13 +24,43 @@ final theme = ThemeData( TextTheme( headline1: headline1Style, headline2: headline2Style, - caption: captionStyle, + caption: headline4Style, bodyText1: body1Style, subtitle1: TextStyle(fontSize: 15, height: 1.6), // text input style ), ), ); +var darkTheme = ligtTheme.copyWith( + brightness: Brightness.dark, + scaffoldBackgroundColor: Color(0xFF202120), + iconTheme: IconThemeData(color: BrandColors.gray3), + cardColor: BrandColors.gray1, + textTheme: GoogleFonts.interTextTheme( + TextTheme( + headline1: headline1Style.copyWith(color: BrandColors.white), + headline2: headline2Style.copyWith(color: BrandColors.white), + caption: headline4Style.copyWith(color: BrandColors.white), + bodyText1: body1Style.copyWith(color: BrandColors.white), + subtitle1: TextStyle(fontSize: 15, height: 1.6), // text input style + ), + ), + inputDecorationTheme: InputDecorationTheme( + labelStyle: TextStyle(color: BrandColors.white), + hintStyle: TextStyle(color: BrandColors.white), + border: OutlineInputBorder( + borderSide: BorderSide( + color: BrandColors.white, + ), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: BrandColors.white, + ), + ), + ), +); + final brandPagePadding1 = EdgeInsets.symmetric(horizontal: 15, vertical: 30); final brandPagePadding2 = EdgeInsets.symmetric(horizontal: 15); diff --git a/lib/config/text_themes.dart b/lib/config/text_themes.dart index 17a95ef6af..5be2aa5c10 100644 --- a/lib/config/text_themes.dart +++ b/lib/config/text_themes.dart @@ -29,7 +29,7 @@ final headline3Style = GoogleFonts.inter( color: BrandColors.headlineColor, ); -final captionStyle = GoogleFonts.inter( +final headline4Style = GoogleFonts.inter( fontSize: 18, fontWeight: NamedFontWeight.medium, color: BrandColors.headlineColor, diff --git a/lib/logic/cubit/app_settings/app_settings_cubit.dart b/lib/logic/cubit/app_settings/app_settings_cubit.dart new file mode 100644 index 0000000000..a14f1577e9 --- /dev/null +++ b/lib/logic/cubit/app_settings/app_settings_cubit.dart @@ -0,0 +1,18 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/widgets.dart'; +export 'package:provider/provider.dart'; + +part 'app_settings_state.dart'; + +class AppSettingsCubit extends Cubit { + AppSettingsCubit({ + bool isDarkModeOn, + }) : super( + AppSettingsState(isDarkModeOn: isDarkModeOn), + ); + + void update({@required bool isDarkModeOn}) { + emit(AppSettingsState(isDarkModeOn: isDarkModeOn)); + } +} diff --git a/lib/logic/cubit/app_settings/app_settings_state.dart b/lib/logic/cubit/app_settings/app_settings_state.dart new file mode 100644 index 0000000000..1ad6840474 --- /dev/null +++ b/lib/logic/cubit/app_settings/app_settings_state.dart @@ -0,0 +1,12 @@ +part of 'app_settings_cubit.dart'; + +class AppSettingsState extends Equatable { + const AppSettingsState({ + @required this.isDarkModeOn, + }); + + final bool isDarkModeOn; + + @override + List get props => [isDarkModeOn]; +} diff --git a/lib/main.dart b/lib/main.dart index d6f113bf7d..61f8194e90 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:selfprivacy/ui/pages/rootRoute.dart'; import 'config/bloc_config.dart'; import 'config/brand_theme.dart'; import 'config/localization.dart'; +import 'logic/cubit/app_settings/app_settings_cubit.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -20,21 +21,22 @@ void main() { ); } -var _showOnbording = false; +var _showOnbording = true; class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return AnnotatedRegion( value: SystemUiOverlayStyle.light, // Manually changnig appbar color - child: MaterialApp( localizationsDelegates: context.localizationDelegates, supportedLocales: context.supportedLocales, locale: context.locale, debugShowCheckedModeBanner: false, title: 'SelfPrivacy', - theme: theme, + theme: context.watch().state.isDarkModeOn + ? darkTheme + : ligtTheme, home: _showOnbording ? OnboardingPage() : RootPage(), ), ); diff --git a/lib/ui/components/brand_button/brand_button.dart b/lib/ui/components/brand_button/brand_button.dart index c3cc5728ea..d410a4d447 100644 --- a/lib/ui/components/brand_button/brand_button.dart +++ b/lib/ui/components/brand_button/brand_button.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; enum BrandButtonTypes { rised, text, iconText } @@ -182,9 +182,7 @@ class _IconTextButton extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - title, - ).body1, + BrandText.body1(title), Padding( padding: const EdgeInsets.all(12.0), child: icon, diff --git a/lib/ui/components/brand_card/brand_card.dart b/lib/ui/components/brand_card/brand_card.dart index 67d741d090..632ebd95f5 100644 --- a/lib/ui/components/brand_card/brand_card.dart +++ b/lib/ui/components/brand_card/brand_card.dart @@ -12,7 +12,9 @@ class BrandCard extends StatelessWidget { return Container( margin: EdgeInsets.only(bottom: 30), decoration: BoxDecoration( - color: BrandColors.white, + color: Theme.of(context).brightness == Brightness.dark + ? BrandColors.black + : BrandColors.white, borderRadius: BorderRadius.circular(20), ).ev8, padding: EdgeInsets.symmetric( diff --git a/lib/ui/components/brand_header/brand_header.dart b/lib/ui/components/brand_header/brand_header.dart index 0c2bc5d442..cff4d41a7c 100644 --- a/lib/ui/components/brand_header/brand_header.dart +++ b/lib/ui/components/brand_header/brand_header.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class BrandHeader extends StatelessWidget { const BrandHeader({ @@ -30,7 +30,7 @@ class BrandHeader extends StatelessWidget { ), SizedBox(width: 10), ], - Text(title).caption, + BrandText.h4(title), ], ), ), diff --git a/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart b/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart index a247ee778b..9328321a4c 100644 --- a/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart +++ b/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_colors.dart'; class BrandModalSheet extends StatelessWidget { const BrandModalSheet({ @@ -39,7 +38,7 @@ class BrandModalSheet extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), - color: BrandColors.white, + color: Theme.of(context).scaffoldBackgroundColor, ), width: double.infinity, child: child, diff --git a/lib/ui/components/brand_tab_bar/brand_tab_bar.dart b/lib/ui/components/brand_tab_bar/brand_tab_bar.dart index 18e35b857c..e204ef238e 100644 --- a/lib/ui/components/brand_tab_bar/brand_tab_bar.dart +++ b/lib/ui/components/brand_tab_bar/brand_tab_bar.dart @@ -4,15 +4,15 @@ import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; final _kBottomTabBarHeight = 51; -class BottomTabBar extends StatefulWidget { - BottomTabBar({Key key, this.controller}) : super(key: key); +class BrandTabBar extends StatefulWidget { + BrandTabBar({Key key, this.controller}) : super(key: key); final TabController controller; @override - _BottomTabBarState createState() => _BottomTabBarState(); + _BrandTabBarState createState() => _BrandTabBarState(); } -class _BottomTabBarState extends State { +class _BrandTabBarState extends State { int currentIndex; @override void initState() { @@ -30,11 +30,14 @@ class _BottomTabBarState extends State { @override Widget build(BuildContext context) { final paddingBottom = MediaQuery.of(context).padding.bottom; + return SizedBox( height: paddingBottom + _kBottomTabBarHeight, child: Container( padding: EdgeInsets.symmetric(horizontal: 16), - color: BrandColors.navBackground, + color: Theme.of(context).brightness == Brightness.dark + ? BrandColors.navBackgroundDark + : BrandColors.navBackgroundLight, child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -50,8 +53,10 @@ class _BottomTabBarState extends State { } _getIconButton(String label, IconData iconData, int index) { - var color = - currentIndex == index ? BrandColors.black : BrandColors.inactive; + var acitivColor = Theme.of(context).brightness == Brightness.dark + ? BrandColors.white + : BrandColors.black; + var color = currentIndex == index ? acitivColor : BrandColors.inactive; return InkWell( onTap: () => widget.controller.animateTo(index), child: Padding( diff --git a/lib/ui/components/brand_text/brand_text.dart b/lib/ui/components/brand_text/brand_text.dart new file mode 100644 index 0000000000..fb7cae10d6 --- /dev/null +++ b/lib/ui/components/brand_text/brand_text.dart @@ -0,0 +1,119 @@ +import 'package:flutter/material.dart'; +import 'package:selfprivacy/config/text_themes.dart'; + +enum TextType { + h1, // right now only at onboarding and opened providers + h2, // cards titles + h3, // titles in about page + h4, // caption + body1, // normal + body2, // with opacity + small +} + +class BrandText extends StatelessWidget { + const BrandText( + this.text, { + Key key, + this.style, + @required this.type, + this.overflow, + this.softWrap, + }) : super(key: key); + + final String text; + final TextStyle style; + final TextType type; + final TextOverflow overflow; + final bool softWrap; + + factory BrandText.h1( + String text, { + TextStyle style, + TextOverflow overflow, + bool softWrap, + }) => + BrandText( + text, + type: TextType.h1, + style: style, + ); + factory BrandText.h2(String text, {TextStyle style}) => BrandText( + text, + type: TextType.h2, + style: style, + ); + factory BrandText.h3(String text, {TextStyle style}) => BrandText( + text, + type: TextType.h3, + style: style, + ); + factory BrandText.h4(String text, {TextStyle style}) => BrandText( + text, + type: TextType.h4, + style: style, + ); + factory BrandText.body1(String text, {TextStyle style}) => BrandText( + text, + type: TextType.body1, + style: style, + ); + factory BrandText.body2(String text, {TextStyle style}) => BrandText( + text, + type: TextType.body2, + style: style, + ); + factory BrandText.small(String text, {TextStyle style}) => BrandText( + text, + type: TextType.small, + style: style, + ); + @override + Text build(BuildContext context) { + TextStyle style; + var isDark = Theme.of(context).brightness == Brightness.dark; + + switch (type) { + case TextType.h1: + style = isDark + ? headline1Style.copyWith(color: Colors.white) + : headline1Style; + break; + case TextType.h2: + style = isDark + ? headline2Style.copyWith(color: Colors.white) + : headline2Style; + break; + case TextType.h3: + style = isDark + ? headline3Style.copyWith(color: Colors.white) + : headline3Style; + break; + case TextType.h4: + style = isDark + ? headline4Style.copyWith(color: Colors.white) + : headline4Style; + break; + case TextType.body1: + style = isDark ? body1Style.copyWith(color: Colors.white) : body1Style; + break; + case TextType.body2: + style = isDark + ? body2Style.copyWith(color: Colors.white.withOpacity(0.6)) + : body2Style; + break; + case TextType.small: + style = isDark ? smallStyle.copyWith(color: Colors.white) : smallStyle; + break; + } + if (this.style != null) { + style = style.merge(this.style); + } + return Text( + text, + style: style, + overflow: overflow, + softWrap: softWrap, + ); + } +} diff --git a/lib/ui/components/switch_block/switch_bloc.dart b/lib/ui/components/switch_block/switch_bloc.dart index 1f88512bc7..57403bea3d 100644 --- a/lib/ui/components/switch_block/switch_bloc.dart +++ b/lib/ui/components/switch_block/switch_bloc.dart @@ -6,10 +6,12 @@ class SwitcherBlock extends StatelessWidget { Key key, @required this.child, @required this.isActive, + @required this.onChange, }) : super(key: key); final Widget child; final bool isActive; + final ValueChanged onChange; @override Widget build(BuildContext context) { @@ -28,7 +30,7 @@ class SwitcherBlock extends StatelessWidget { Switch( activeColor: BrandColors.green1, activeTrackColor: BrandColors.green2, - onChanged: (v) {}, + onChanged: onChange, value: isActive, ), ], diff --git a/lib/ui/pages/more/about/about.dart b/lib/ui/pages/more/about/about.dart index 0f7e6fa505..d106f9f8bd 100644 --- a/lib/ui/pages/more/about/about.dart +++ b/lib/ui/pages/more/about/about.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class AboutPage extends StatelessWidget { const AboutPage({Key key}) : super(key: key); @@ -20,28 +20,28 @@ class AboutPage extends StatelessWidget { children: [ BrandDivider(), SizedBox(height: 20), - Text('О проекте').h3, + BrandText.h3('О проекте'), SizedBox(height: 10), - Text('Всё больше организаций хотят владеть нашими данными').body1, + BrandText.body1( + 'Всё больше организаций хотят владеть нашими данными'), SizedBox(height: 10), - Text('А мы сами хотим распоряжаться своими данными на своем сервере.') - .body1, + BrandText.body1( + 'А мы сами хотим распоряжаться своими данными на своем сервере.'), SizedBox(height: 20), BrandDivider(), SizedBox(height: 10), - Text('Миссия проекта').h3, + BrandText.h3('Миссия проекта'), SizedBox(height: 10), - Text('Цифровая независимость и приватность доступная каждому'), + BrandText.body1( + 'Цифровая независимость и приватность доступная каждому'), SizedBox(height: 20), BrandDivider(), SizedBox(height: 10), - Text('Цель').h3, + BrandText.h3('Цель'), SizedBox(height: 10), - Text( + BrandText.body1( 'Развивать программу, которая позволит каждому создавать приватные сервисы для себя и своих близких'), SizedBox(height: 10), - Text( - 'Развивать программу, которая позволит каждому создавать приватные сервисы для себя и своих близких'), ], ), ), diff --git a/lib/ui/pages/more/app_settings/app_setting.dart b/lib/ui/pages/more/app_settings/app_setting.dart index 6399fc2a88..7988ee008a 100644 --- a/lib/ui/pages/more/app_settings/app_setting.dart +++ b/lib/ui/pages/more/app_settings/app_setting.dart @@ -1,37 +1,68 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_theme.dart'; +import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; -import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; -class AppSettingsPage extends StatelessWidget { +class AppSettingsPage extends StatefulWidget { const AppSettingsPage({Key key}) : super(key: key); + @override + _AppSettingsPageState createState() => _AppSettingsPageState(); +} + +class _AppSettingsPageState extends State { @override Widget build(BuildContext context) { + var appSettings = context.watch(); + + var isDarkModeOn = appSettings.state.isDarkModeOn; + return SafeArea( - child: Scaffold( - appBar: PreferredSize( - child: - BrandHeader(title: 'Настройки приложения', hasBackButton: true), - preferredSize: Size.fromHeight(52), - ), - body: ListView( - padding: brandPagePadding2, - children: [ - BrandDivider(), - SwitcherBlock( - child: _TextColumn( - title: 'Dark Theme', - value: 'Change your the app theme', - ), - isActive: true, - ), - ], - ), - ), + child: Builder(builder: (context) { + return Scaffold( + appBar: PreferredSize( + child: + BrandHeader(title: 'Настройки приложения', hasBackButton: true), + preferredSize: Size.fromHeight(52), + ), + body: ListView( + padding: brandPagePadding2, + children: [ + BrandDivider(), + Container( + padding: EdgeInsets.only(top: 20, bottom: 5), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: BrandColors.dividerColor), + )), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: _TextColumn( + title: 'Dark Theme', + value: 'Change your the app theme', + ), + ), + SizedBox(width: 5), + Switch( + activeColor: BrandColors.green1, + activeTrackColor: BrandColors.green2, + value: Theme.of(context).brightness == Brightness.dark, + onChanged: (value) => + appSettings.update(isDarkModeOn: !isDarkModeOn), + ), + ], + ), + ) + ], + ), + ); + }), ); } } @@ -52,21 +83,21 @@ class _TextColumn extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title).body1.copyWith( - style: TextStyle(color: hasWarning ? BrandColors.warning : null)), + BrandText.body1( + title, + style: TextStyle(color: hasWarning ? BrandColors.warning : null), + ), SizedBox(height: 5), - Text(value) - .body1 - .copyWith( - style: TextStyle( - fontSize: 13, - height: 1.53, - color: BrandColors.gray1, - ), - ) - .copyWith( - style: - TextStyle(color: hasWarning ? BrandColors.warning : null)), + BrandText.body1( + title, + style: TextStyle(color: hasWarning ? BrandColors.warning : null), + ), + BrandText.body1(value, + style: TextStyle( + fontSize: 13, + height: 1.53, + color: BrandColors.gray1, + ).merge(TextStyle(color: hasWarning ? BrandColors.warning : null))), ], ); } diff --git a/lib/ui/pages/more/info/info.dart b/lib/ui/pages/more/info/info.dart index e2506b00bd..68cbd19712 100644 --- a/lib/ui/pages/more/info/info.dart +++ b/lib/ui/pages/more/info/info.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:package_info/package_info.dart'; class InfoPage extends StatelessWidget { @@ -24,9 +24,8 @@ class InfoPage extends StatelessWidget { FutureBuilder( future: _version(), builder: (context, snapshot) { - return Text( - 'Тут любая служебная информация, v.${snapshot.data}') - .body1; + return BrandText.body1( + 'Тут любая служебная информация, v.${snapshot.data}'); }), ], ), diff --git a/lib/ui/pages/more/more.dart b/lib/ui/pages/more/more.dart index dab4e3128b..ea24ba42c2 100644 --- a/lib/ui/pages/more/more.dart +++ b/lib/ui/pages/more/more.dart @@ -4,7 +4,7 @@ import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'about/about.dart'; @@ -80,11 +80,14 @@ class _NavItem extends StatelessWidget { ), child: Row( children: [ - Text(title).body1, + BrandText.body1(title), Spacer(), SizedBox( width: 56, - child: Icon(iconData, size: 20), + child: Icon( + iconData, + size: 20, + ), ), ], ), diff --git a/lib/ui/pages/onboarding/onboarding.dart b/lib/ui/pages/onboarding/onboarding.dart index f23641e6c9..e5adbb8d5d 100644 --- a/lib/ui/pages/onboarding/onboarding.dart +++ b/lib/ui/pages/onboarding/onboarding.dart @@ -1,340 +1,53 @@ import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_theme.dart'; -import 'package:selfprivacy/config/text_themes.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; -import 'package:selfprivacy/ui/components/brand_card/brand_card.dart'; -import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart'; -import 'package:selfprivacy/ui/components/brand_span_button/brand_span_button.dart'; -import 'package:selfprivacy/ui/components/dots_indicator/dots_indicator.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/pages/rootRoute.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; -class OnboardingPage extends StatefulWidget { +class OnboardingPage extends StatelessWidget { const OnboardingPage({Key key}) : super(key: key); - @override - _OnboardingPageState createState() => _OnboardingPageState(); -} - -class _OnboardingPageState extends State { - PageController controller; - var currentPage = 0; - - @override - void initState() { - controller = PageController( - initialPage: 0, - )..addListener(() { - if (currentPage != controller.page.toInt()) { - setState(() { - currentPage = controller.page.toInt(); - }); - } - }); - super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) {}); - } - - @override - void dispose() { - controller.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { - var steps = getSteps(); - return SafeArea( child: Scaffold( - body: ListView( - shrinkWrap: true, - children: [ - Padding( - padding: brandPagePadding1, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Начало').caption, - Text('SelfPrivacy').h1, - SizedBox( - height: 10, - ), - RichText( - text: TextSpan( - children: [ - TextSpan( - text: - 'Для устойчивости и приватности требует много учёток. Полная инструкция на ', - style: body2Style, - ), - BrandSpanButton.link( - text: 'selfprivacy.org/start', - urlString: 'https://selfprivacy.org/start', - ), - ], - ), - ), - ], - ), - ), - Container( - height: 480, - child: PageView.builder( - physics: NeverScrollableScrollPhysics(), - allowImplicitScrolling: false, - controller: controller, - itemBuilder: (_, index) { - return Padding( - padding: brandPagePadding2, - child: steps[index], - ); - }, - itemCount: 4, - ), - ), - DotsIndicator( - activeIndex: currentPage, - count: steps.length, - ), - SizedBox(height: 50), - ], - ), - ), - ); - } - - List getSteps() => [ - BrandCard( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset('assets/images/logos/hetzner.png'), - SizedBox(height: 10), - Text('1. Подключите сервер Hetzner').h2, - SizedBox(height: 10), - Text('Здесь будут жить наши данные и SelfPrivacy-сервисы').body2, - _MockForm( - onPressed: _nextPage, - hintText: 'Hetzner API Token', - length: 2, - ), - SizedBox(height: 20), - Spacer(), - BrandButton.text( - onPressed: () => _showModal(context, _HowHetzner()), - title: 'Как получить API Token', - ), - ], + body: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 45, ), - ), - BrandCard( child: Column( - mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.asset('assets/images/logos/namecheap.png'), - SizedBox(height: 10), - Text('2. Настройте домен ').h2, - SizedBox(height: 10), - RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Зарегистрируйте домен в ', - style: body2Style, - ), - BrandSpanButton.link( - text: 'NameCheap', - urlString: 'https://www.namecheap.com', - ), - TextSpan( - text: - ' или у любого другого регистратора. После этого настройте его на DNS-сервер CloudFlare', - style: body2Style, - ), - ], + Expanded( + child: Align( + alignment: Alignment.centerLeft, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + BrandText.h1( + 'Онбординг', + ), + SizedBox(height: 20), + BrandText.body2( + 'Тут рассказ на 1-2 слайда о том, что делает это приложение, какие твои проблемы решает и как (в общем чего ожидать от сервиса).', + ), + ], + ), ), ), - _MockForm( - onPressed: _nextPage, - hintText: 'Домен, например, selfprivacy.org', - submitButtonText: 'Проверить DNS', - length: 2, - ), - Spacer(), - BrandButton.text( - onPressed: () {}, - title: 'Как настроить DNS CloudFlare', - ), - ], - ), - ), - BrandCard( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset('assets/images/logos/cloudflare.png'), - SizedBox(height: 10), - Text('3. Подключите CloudFlare DNS').h2, - SizedBox(height: 10), - Text('Для управления DNS вашего домена').body2, - _MockForm( - onPressed: _nextPage, - hintText: 'CloudFlare API Token', - length: 2, - ), - Spacer(), - BrandButton.text( - onPressed: () {}, - title: 'Как получить API Token', - ), - ], - ), - ), - BrandCard( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset('assets/images/logos/aws.png'), - SizedBox(height: 10), - Text('4. Подключите Amazon AWS для бекапа').h2, - SizedBox(height: 10), - Text('IaaS-провайдер, для бесплатного хранения резервных копии ваших данных в зашифрованном виде') - .body2, - _MockForm( + BrandButton.rised( onPressed: () { Navigator.of(context) .pushReplacement(materialRoute(RootPage())); }, - hintText: 'Amazon AWS Access Key', - length: 2, - ), - Spacer(), - BrandButton.text( - onPressed: () {}, - title: 'Как получить API Token', - ), + title: 'Приступим!', + ) ], ), ), - ]; - - void _showModal(BuildContext context, Widget widget) { - showModalBottomSheet( - context: context, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (BuildContext context) { - return widget; - }, - ); - } - - void _nextPage() => controller.nextPage( - duration: Duration(milliseconds: 300), - curve: Curves.easeIn, - ); -} - -class _HowHetzner extends StatelessWidget { - const _HowHetzner({ - Key key, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return BrandModalSheet( - child: Padding( - padding: brandPagePadding2, - child: Column( - children: [ - SizedBox(height: 40), - Text('Как получить Hetzner API Token').h2, - SizedBox(height: 20), - RichText( - text: TextSpan( - children: [ - TextSpan( - text: '1 Переходим по ссылке ', - style: body1Style, - ), - BrandSpanButton.link( - text: 'hetzner.com/sdfsdfsdfsdf', - urlString: 'https://hetzner.com/sdfsdfsdfsdf', - ), - TextSpan( - text: ''' - -2 Заходим в созданный нами проект. Если такового - нет, значит создаём. - -3 Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика). - -4 Далее, в верхней части интерфейса видим примерно такой список: SSH Keys, API Tokens, Certificates, Members. Нам нужен API Tokens. Переходим по нему. - -5 В правой части интерфейса, нас будет ожидать кнопка Generate API token. Если же вы используете мобильную версию сайта, в нижнем правом углу вы увидите красный плюсик. Нажимаем на эту кнопку. - -6 В поле Description, даём нашему токену название (это может быть любое название, которые вам нравиться. Сути оно не меняет. - - ''', - style: body1Style, - ), - ], - ), - ), - ], - ), ), ); } } - -class _MockForm extends StatefulWidget { - const _MockForm({ - Key key, - @required this.hintText, - this.submitButtonText = 'Подключить', - @required this.onPressed, - @required this.length, - }) : super(key: key); - - final String hintText; - final String submitButtonText; - final int length; - - final VoidCallback onPressed; - - @override - __MockFormState createState() => __MockFormState(); -} - -class __MockFormState extends State<_MockForm> { - String text = ''; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - SizedBox(height: 20), - TextField( - onChanged: (value) => { - setState(() { - text = value; - }) - }, - decoration: InputDecoration(hintText: widget.hintText), - ), - SizedBox(height: 20), - BrandButton.rised( - onPressed: - text.length == widget.length ? widget.onPressed ?? () {} : null, - title: widget.submitButtonText, - ), - ], - ); - } -} diff --git a/lib/ui/pages/onboarding/onboarding copy.dart b/lib/ui/pages/onboarding/onboarding.full.dart similarity index 79% rename from lib/ui/pages/onboarding/onboarding copy.dart rename to lib/ui/pages/onboarding/onboarding.full.dart index 1a4685fb1d..cf311f46ca 100644 --- a/lib/ui/pages/onboarding/onboarding copy.dart +++ b/lib/ui/pages/onboarding/onboarding.full.dart @@ -5,7 +5,7 @@ import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_card/brand_card.dart'; import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart'; import 'package:selfprivacy/ui/components/brand_span_button/brand_span_button.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class OnboardingPage extends StatelessWidget { const OnboardingPage({Key key}) : super(key: key); @@ -16,8 +16,8 @@ class OnboardingPage extends StatelessWidget { body: ListView( padding: brandPagePadding1, children: [ - Text('Начало').caption, - Text('SelfPrivacy').h1, + BrandText.h4('Начало'), + BrandText.h1('SelfPrivacy'), SizedBox( height: 10, ), @@ -43,10 +43,10 @@ class OnboardingPage extends StatelessWidget { children: [ Image.asset('assets/images/logos/hetzner.png'), SizedBox(height: 10), - Text('1. Подключите сервер Hetzner').h2, + BrandText.h2('1. Подключите сервер Hetzner'), SizedBox(height: 10), - Text('Здесь будут жить наши данные и SelfPrivacy-сервисы') - .body2, + BrandText.body2( + 'Здесь будут жить наши данные и SelfPrivacy-сервисы'), _MockForm( hintText: 'Hetzner API Token', ), @@ -64,7 +64,7 @@ class OnboardingPage extends StatelessWidget { children: [ Image.asset('assets/images/logos/namecheap.png'), SizedBox(height: 10), - Text('2. Настройте домен ').h2, + BrandText.h2('2. Настройте домен'), SizedBox(height: 10), RichText( text: TextSpan( @@ -103,9 +103,9 @@ class OnboardingPage extends StatelessWidget { children: [ Image.asset('assets/images/logos/cloudflare.png'), SizedBox(height: 10), - Text('3. Подключите CloudFlare DNS').h2, + BrandText.h2('3. Подключите CloudFlare DNS'), SizedBox(height: 10), - Text('Для управления DNS вашего домена').body2, + BrandText.body2('Для управления DNS вашего домена'), _MockForm( hintText: 'CloudFlare API Token', ), @@ -123,10 +123,10 @@ class OnboardingPage extends StatelessWidget { children: [ Image.asset('assets/images/logos/aws.png'), SizedBox(height: 10), - Text('4. Подключите Amazon AWS для бекапа').h2, + BrandText.h2('4. Подключите Amazon AWS для бекапа'), SizedBox(height: 10), - Text('IaaS-провайдер, для бесплатного хранения резервных копии ваших данных в зашифрованном виде') - .body2, + BrandText.body2( + 'IaaS-провайдер, для бесплатного хранения резервных копии ваших данных в зашифрованном виде'), _MockForm( hintText: 'Amazon AWS Access Key', ), @@ -163,25 +163,27 @@ class _HowHetzner extends StatelessWidget { @override Widget build(BuildContext context) { return BrandModalSheet( - child: Column( - children: [ - SizedBox(height: 40), - Text('Как получить Hetzner API Token').h2, - SizedBox(height: 20), - RichText( - text: TextSpan( - children: [ - TextSpan( - text: '1 Переходим по ссылке ', - style: body1Style, - ), - BrandSpanButton.link( - text: 'hetzner.com/sdfsdfsdfsdf', - urlString: 'https://hetzner.com/sdfsdfsdfsdf', - ), - TextSpan( - text: ''' - + child: Padding( + padding: brandPagePadding2, + child: Column( + children: [ + SizedBox(height: 40), + BrandText.h2('Как получить Hetzner API Token'), + SizedBox(height: 20), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: '1 Переходим по ссылке ', + style: body1Style, + ), + BrandSpanButton.link( + text: 'hetzner.com/sdfsdfsdfsdf', + urlString: 'https://hetzner.com/sdfsdfsdfsdf', + ), + TextSpan( + text: ''' + 2 Заходим в созданный нами проект. Если такового - нет, значит создаём. 3 Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика). @@ -192,13 +194,14 @@ class _HowHetzner extends StatelessWidget { 6 В поле Description, даём нашему токену название (это может быть любое название, которые вам нравиться. Сути оно не меняет. - ''', - style: body1Style, - ), - ], + ''', + style: body1Style, + ), + ], + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/ui/pages/onboarding/onboarding.old.dart b/lib/ui/pages/onboarding/onboarding.old.dart new file mode 100644 index 0000000000..717c084df5 --- /dev/null +++ b/lib/ui/pages/onboarding/onboarding.old.dart @@ -0,0 +1,340 @@ +// import 'package:flutter/material.dart'; +// import 'package:selfprivacy/config/brand_theme.dart'; +// import 'package:selfprivacy/config/text_themes.dart'; +// import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; +// import 'package:selfprivacy/ui/components/brand_card/brand_card.dart'; +// import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart'; +// import 'package:selfprivacy/ui/components/brand_span_button/brand_span_button.dart'; +// import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; +// import 'package:selfprivacy/ui/components/dots_indicator/dots_indicator.dart'; +// import 'package:selfprivacy/ui/pages/rootRoute.dart'; +// import 'package:selfprivacy/utils/route_transitions/basic.dart'; + +// class OnboardingPage extends StatefulWidget { +// const OnboardingPage({Key key}) : super(key: key); + +// @override +// _OnboardingPageState createState() => _OnboardingPageState(); +// } + +// class _OnboardingPageState extends State { +// PageController controller; +// var currentPage = 0; + +// @override +// void initState() { +// controller = PageController( +// initialPage: 0, +// )..addListener(() { +// if (currentPage != controller.page.toInt()) { +// setState(() { +// currentPage = controller.page.toInt(); +// }); +// } +// }); +// super.initState(); +// WidgetsBinding.instance.addPostFrameCallback((_) {}); +// } + +// @override +// void dispose() { +// controller.dispose(); +// super.dispose(); +// } + +// @override +// Widget build(BuildContext context) { +// var steps = getSteps(); + +// return SafeArea( +// child: Scaffold( +// body: ListView( +// shrinkWrap: true, +// children: [ +// Padding( +// padding: brandPagePadding1, +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// BrandText.h4('Начало'), +// BrandText.h1('SelfPrivacy'), +// SizedBox( +// height: 10, +// ), +// RichText( +// text: TextSpan( +// children: [ +// TextSpan( +// text: +// 'Для устойчивости и приватности требует много учёток. Полная инструкция на ', +// style: body2Style, +// ), +// BrandSpanButton.link( +// text: 'selfprivacy.org/start', +// urlString: 'https://selfprivacy.org/start', +// ), +// ], +// ), +// ), +// ], +// ), +// ), +// Container( +// height: 480, +// child: PageView.builder( +// physics: NeverScrollableScrollPhysics(), +// allowImplicitScrolling: false, +// controller: controller, +// itemBuilder: (_, index) { +// return Padding( +// padding: brandPagePadding2, +// child: steps[index], +// ); +// }, +// itemCount: 4, +// ), +// ), +// DotsIndicator( +// activeIndex: currentPage, +// count: steps.length, +// ), +// SizedBox(height: 50), +// ], +// ), +// ), +// ); +// } + +// List getSteps() => [ +// BrandCard( +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Image.asset('assets/images/logos/hetzner.png'), +// SizedBox(height: 10), +// Text('1. Подключите сервер Hetzner').h2, +// SizedBox(height: 10), +// Text('Здесь будут жить наши данные и SelfPrivacy-сервисы').body2, +// _MockForm( +// onPressed: _nextPage, +// hintText: 'Hetzner API Token', +// length: 2, +// ), +// SizedBox(height: 20), +// Spacer(), +// BrandButton.text( +// onPressed: () => _showModal(context, _HowHetzner()), +// title: 'Как получить API Token', +// ), +// ], +// ), +// ), +// BrandCard( +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Image.asset('assets/images/logos/namecheap.png'), +// SizedBox(height: 10), +// Text('2. Настройте домен ').h2, +// SizedBox(height: 10), +// RichText( +// text: TextSpan( +// children: [ +// TextSpan( +// text: 'Зарегистрируйте домен в ', +// style: body2Style, +// ), +// BrandSpanButton.link( +// text: 'NameCheap', +// urlString: 'https://www.namecheap.com', +// ), +// TextSpan( +// text: +// ' или у любого другого регистратора. После этого настройте его на DNS-сервер CloudFlare', +// style: body2Style, +// ), +// ], +// ), +// ), +// _MockForm( +// onPressed: _nextPage, +// hintText: 'Домен, например, selfprivacy.org', +// submitButtonText: 'Проверить DNS', +// length: 2, +// ), +// Spacer(), +// BrandButton.text( +// onPressed: () {}, +// title: 'Как настроить DNS CloudFlare', +// ), +// ], +// ), +// ), +// BrandCard( +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Image.asset('assets/images/logos/cloudflare.png'), +// SizedBox(height: 10), +// Text('3. Подключите CloudFlare DNS').h2, +// SizedBox(height: 10), +// Text('Для управления DNS вашего домена').body2, +// _MockForm( +// onPressed: _nextPage, +// hintText: 'CloudFlare API Token', +// length: 2, +// ), +// Spacer(), +// BrandButton.text( +// onPressed: () {}, +// title: 'Как получить API Token', +// ), +// ], +// ), +// ), +// BrandCard( +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Image.asset('assets/images/logos/aws.png'), +// SizedBox(height: 10), +// Text('4. Подключите Amazon AWS для бекапа').h2, +// SizedBox(height: 10), +// Text('IaaS-провайдер, для бесплатного хранения резервных копии ваших данных в зашифрованном виде') +// .body2, +// _MockForm( +// onPressed: () { +// Navigator.of(context) +// .pushReplacement(materialRoute(RootPage())); +// }, +// hintText: 'Amazon AWS Access Key', +// length: 2, +// ), +// Spacer(), +// BrandButton.text( +// onPressed: () {}, +// title: 'Как получить API Token', +// ), +// ], +// ), +// ), +// ]; + +// void _showModal(BuildContext context, Widget widget) { +// showModalBottomSheet( +// context: context, +// isScrollControlled: true, +// backgroundColor: Colors.transparent, +// builder: (BuildContext context) { +// return widget; +// }, +// ); +// } + +// void _nextPage() => controller.nextPage( +// duration: Duration(milliseconds: 300), +// curve: Curves.easeIn, +// ); +// } + +// class _HowHetzner extends StatelessWidget { +// const _HowHetzner({ +// Key key, +// }) : super(key: key); + +// @override +// Widget build(BuildContext context) { +// return BrandModalSheet( +// child: Padding( +// padding: brandPagePadding2, +// child: Column( +// children: [ +// SizedBox(height: 40), +// Text('Как получить Hetzner API Token').h2, +// SizedBox(height: 20), +// RichText( +// text: TextSpan( +// children: [ +// TextSpan( +// text: '1 Переходим по ссылке ', +// style: body1Style, +// ), +// BrandSpanButton.link( +// text: 'hetzner.com/sdfsdfsdfsdf', +// urlString: 'https://hetzner.com/sdfsdfsdfsdf', +// ), +// TextSpan( +// text: ''' + +// 2 Заходим в созданный нами проект. Если такового - нет, значит создаём. + +// 3 Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика). + +// 4 Далее, в верхней части интерфейса видим примерно такой список: SSH Keys, API Tokens, Certificates, Members. Нам нужен API Tokens. Переходим по нему. + +// 5 В правой части интерфейса, нас будет ожидать кнопка Generate API token. Если же вы используете мобильную версию сайта, в нижнем правом углу вы увидите красный плюсик. Нажимаем на эту кнопку. + +// 6 В поле Description, даём нашему токену название (это может быть любое название, которые вам нравиться. Сути оно не меняет. + +// ''', +// style: body1Style, +// ), +// ], +// ), +// ), +// ], +// ), +// ), +// ); +// } +// } + +// class _MockForm extends StatefulWidget { +// const _MockForm({ +// Key key, +// @required this.hintText, +// this.submitButtonText = 'Подключить', +// @required this.onPressed, +// @required this.length, +// }) : super(key: key); + +// final String hintText; +// final String submitButtonText; +// final int length; + +// final VoidCallback onPressed; + +// @override +// __MockFormState createState() => __MockFormState(); +// } + +// class __MockFormState extends State<_MockForm> { +// String text = ''; + +// @override +// Widget build(BuildContext context) { +// return Column( +// children: [ +// SizedBox(height: 20), +// TextField( +// onChanged: (value) => { +// setState(() { +// text = value; +// }) +// }, +// decoration: InputDecoration(hintText: widget.hintText), +// ), +// SizedBox(height: 20), +// BrandButton.rised( +// onPressed: +// text.length == widget.length ? widget.onPressed ?? () {} : null, +// title: widget.submitButtonText, +// ), +// ], +// ); +// } +// } diff --git a/lib/ui/pages/providers/providers.dart b/lib/ui/pages/providers/providers.dart index fe3095497c..f05ed7ff63 100644 --- a/lib/ui/pages/providers/providers.dart +++ b/lib/ui/pages/providers/providers.dart @@ -5,9 +5,9 @@ import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/ui/components/brand_card/brand_card.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.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/pages/providers/settings/setting.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; class ProvidersPage extends StatefulWidget { @@ -85,14 +85,14 @@ class _Card extends StatelessWidget { child: Icon(provider.icon, size: 30, color: Colors.white), ), SizedBox(height: 10), - Text(title).h2, + BrandText.h2(title), SizedBox(height: 10), if (message != null) ...[ - Text(message).body2, + BrandText.body2(message), SizedBox(height: 10), ], if (provider.state == ServiceStateType.stable) - Text(stableText).body2, + BrandText.body2(stableText), ], ), ), @@ -173,9 +173,9 @@ class _ProviderDetails extends StatelessWidget { child: Icon(provider.icon, size: 40, color: Colors.white), ), SizedBox(height: 10), - Text(title).h1, + BrandText.h1(title), SizedBox(height: 10), - Text(statusText).body1, + BrandText.body1(statusText), SizedBox( height: 20, ), diff --git a/lib/ui/pages/providers/settings/setting.dart b/lib/ui/pages/providers/settings/setting.dart index a53def8a50..20f913f8d8 100644 --- a/lib/ui/pages/providers/settings/setting.dart +++ b/lib/ui/pages/providers/settings/setting.dart @@ -3,8 +3,8 @@ import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; class SettingsPage extends StatelessWidget { const SettingsPage({Key key}) : super(key: key); @@ -22,6 +22,7 @@ class SettingsPage extends StatelessWidget { children: [ BrandDivider(), SwitcherBlock( + onChange: (_) {}, child: _TextColumn( title: 'Allow Auto-upgrade', value: 'Wether to allow automatic packages upgrades', @@ -29,6 +30,7 @@ class SettingsPage extends StatelessWidget { isActive: true, ), SwitcherBlock( + onChange: (_) {}, child: _TextColumn( title: 'Reboot after upgrade', value: 'Reboot without prompt after applying updates', @@ -106,21 +108,19 @@ class _TextColumn extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(title).body1.copyWith( - style: TextStyle(color: hasWarning ? BrandColors.warning : null)), + BrandText.body1( + title, + style: TextStyle(color: hasWarning ? BrandColors.warning : null), + ), SizedBox(height: 5), - Text(value) - .body1 - .copyWith( - style: TextStyle( - fontSize: 13, - height: 1.53, - color: BrandColors.gray1, - ), - ) - .copyWith( - style: - TextStyle(color: hasWarning ? BrandColors.warning : null)), + BrandText.body1( + value, + style: TextStyle( + fontSize: 13, + height: 1.53, + color: hasWarning ? BrandColors.warning : BrandColors.gray1, + ), + ), ], ); } diff --git a/lib/ui/pages/rootRoute.dart b/lib/ui/pages/rootRoute.dart index 5fc59df588..dcb9c38e46 100644 --- a/lib/ui/pages/rootRoute.dart +++ b/lib/ui/pages/rootRoute.dart @@ -42,7 +42,7 @@ class _RootPageState extends State MorePage(), ], ), - bottomNavigationBar: BottomTabBar( + bottomNavigationBar: BrandTabBar( controller: tabController, ), ), diff --git a/lib/ui/pages/services/services.dart b/lib/ui/pages/services/services.dart index 71dbf51fc0..2762e4b30e 100644 --- a/lib/ui/pages/services/services.dart +++ b/lib/ui/pages/services/services.dart @@ -6,8 +6,8 @@ import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_card/brand_card.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.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/utils/extensions/text_extension.dart'; class ServicesPage extends StatefulWidget { ServicesPage({Key key}) : super(key: key); @@ -33,7 +33,7 @@ class _ServicesPageState extends State { SizedBox(height: 24), ...connected.map((service) => _Card(service: service)).toList(), if (uninitialized.isNotEmpty) ...[ - Text('не подключены').body1, + BrandText.body1('не подключены'), SizedBox(height: 30), ], ...uninitialized.map((service) => _Card(service: service)).toList() @@ -91,10 +91,10 @@ class _Card extends StatelessWidget { child: Icon(iconData, size: 30, color: Colors.white), ), SizedBox(height: 10), - Text(title).h2, + BrandText.h2(title), SizedBox(height: 10), if (service.state == ServiceStateType.uninitialized) ...[ - Text(description).body1, + BrandText.body1(description), SizedBox(height: 10), BrandButton.text( title: 'Подключить', @@ -102,7 +102,8 @@ class _Card extends StatelessWidget { context.read().connect(service); }) ], - if (service.state == ServiceStateType.stable) Text('Подключен').body1, + if (service.state == ServiceStateType.stable) + BrandText.body2('Подключен'), ], ), ); diff --git a/lib/ui/pages/users/users.dart b/lib/ui/pages/users/users.dart index 7209c6face..5bfebb1cca 100644 --- a/lib/ui/pages/users/users.dart +++ b/lib/ui/pages/users/users.dart @@ -8,7 +8,7 @@ import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart'; -import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/utils/password_generator.dart'; class UsersPage extends StatelessWidget { @@ -88,7 +88,7 @@ class _User extends StatelessWidget { ), ), SizedBox(width: 20), - Text(user.login).caption, + BrandText.h4(user.login), ], ), ), @@ -267,16 +267,15 @@ class _UserDetails extends StatelessWidget { ), Spacer(), Padding( - padding: EdgeInsets.symmetric( - vertical: 20, - horizontal: 15, - ), - child: Text( - user.login, - softWrap: true, - overflow: TextOverflow.ellipsis, - ).h1, - ), + padding: EdgeInsets.symmetric( + vertical: 20, + horizontal: 15, + ), + child: BrandText.h1( + user.login, + softWrap: true, + overflow: TextOverflow.ellipsis, + )), ], ), ), @@ -286,18 +285,18 @@ class _UserDetails extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Учетная запись').small, + BrandText.small('Учетная запись'), Container( height: 40, alignment: Alignment.centerLeft, - child: Text('${user.login}@example.com').caption, + child: BrandText.h4('${user.login}@example.com'), ), SizedBox(height: 14), - Text('Пароль').small, + BrandText.small('Пароль'), Container( height: 40, alignment: Alignment.centerLeft, - child: Text(user.password).caption, + child: BrandText.h4(user.password), ), SizedBox(height: 24), BrandDivider(), diff --git a/lib/utils/extensions/text_extension.dart b/lib/utils/extensions/text_extension.dart index 45631fd5bf..039785de9f 100644 --- a/lib/utils/extensions/text_extension.dart +++ b/lib/utils/extensions/text_extension.dart @@ -1,47 +1,47 @@ -library text_extension; +// library text_extension; -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:selfprivacy/config/text_themes.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter/cupertino.dart'; +// import 'package:selfprivacy/config/text_themes.dart'; -extension TextExtension on Text { - Text get h1 => copyWith(style: headline1Style); - Text get h2 => copyWith(style: headline2Style); - Text get h3 => copyWith(style: headline3Style); +// extension TextExtension on Text { +// Text get h1 => copyWith(style: headline1Style); +// Text get h2 => copyWith(style: headline2Style); +// Text get h3 => copyWith(style: headline3Style); - Text get caption => copyWith(style: captionStyle); +// Text get caption => copyWith(style: headline4Style); - Text get body1 => copyWith(style: body1Style); - Text get body2 => copyWith(style: body2Style); - Text get small => copyWith(style: smallStyle); +// Text get body1 => copyWith(style: body1Style); +// Text get body2 => copyWith(style: body2Style); +// Text get small => copyWith(style: smallStyle); - Text setKey(Key key) => copyWith(key: key); +// Text setKey(Key key) => copyWith(key: key); - Text copyWith( - {Key key, - StrutStyle strutStyle, - TextAlign textAlign, - TextDirection textDirection = TextDirection.ltr, - Locale locale, - bool softWrap, - TextOverflow overflow, - double textScaleFactor, - int maxLines, - String semanticsLabel, - TextWidthBasis textWidthBasis, - TextStyle style}) { - return Text(data, - key: key ?? this.key, - strutStyle: strutStyle ?? this.strutStyle, - textAlign: textAlign ?? this.textAlign, - textDirection: textDirection ?? this.textDirection, - locale: locale ?? this.locale, - softWrap: softWrap ?? this.softWrap, - overflow: overflow ?? this.overflow, - textScaleFactor: textScaleFactor ?? this.textScaleFactor, - maxLines: maxLines ?? this.maxLines, - semanticsLabel: semanticsLabel ?? this.semanticsLabel, - textWidthBasis: textWidthBasis ?? this.textWidthBasis, - style: style != null ? this.style?.merge(style) ?? style : this.style); - } -} +// Text copyWith( +// {Key key, +// StrutStyle strutStyle, +// TextAlign textAlign, +// TextDirection textDirection = TextDirection.ltr, +// Locale locale, +// bool softWrap, +// TextOverflow overflow, +// double textScaleFactor, +// int maxLines, +// String semanticsLabel, +// TextWidthBasis textWidthBasis, +// TextStyle style}) { +// return Text(data, +// key: key ?? this.key, +// strutStyle: strutStyle ?? this.strutStyle, +// textAlign: textAlign ?? this.textAlign, +// textDirection: textDirection ?? this.textDirection, +// locale: locale ?? this.locale, +// softWrap: softWrap ?? this.softWrap, +// overflow: overflow ?? this.overflow, +// textScaleFactor: textScaleFactor ?? this.textScaleFactor, +// maxLines: maxLines ?? this.maxLines, +// semanticsLabel: semanticsLabel ?? this.semanticsLabel, +// textWidthBasis: textWidthBasis ?? this.textWidthBasis, +// style: style != null ? this.style?.merge(style) ?? style : this.style); +// } +// }