From 4875e3ee0786ed7986cb344bf745be0daf1521a8 Mon Sep 17 00:00:00 2001 From: Kherel Date: Wed, 2 Dec 2020 10:16:23 +0100 Subject: [PATCH] add more --- assets/fonts/BrandIcons.ttf | Bin 7040 -> 7116 bytes ios/Podfile.lock | 6 + lib/config/brand_colors.dart | 14 ++ lib/config/brand_theme.dart | 4 +- lib/config/text_themes.dart | 6 + .../brand_divider/brand_divider.dart | 16 ++ .../components/brand_header/brand_header.dart | 39 +++++ .../components/brand_icons/brand_icons.dart | 2 + lib/ui/pages/about/about.dart | 56 ++++++ lib/ui/pages/info/info.dart | 46 +++++ lib/ui/pages/more/more.dart | 86 +++++++++ lib/ui/pages/onboarding/onboarding.dart | 3 +- lib/ui/pages/rootRoute.dart | 3 +- lib/ui/pages/servers/servers.dart | 2 +- lib/ui/pages/services/services.dart | 2 +- lib/ui/pages/settings/setting.dart | 165 ++++++++++++++++++ lib/utils/extensions/text_extension.dart | 2 + pubspec.lock | 7 + pubspec.yaml | 3 +- 19 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 lib/ui/components/brand_divider/brand_divider.dart create mode 100644 lib/ui/components/brand_header/brand_header.dart create mode 100644 lib/ui/pages/about/about.dart create mode 100644 lib/ui/pages/info/info.dart create mode 100644 lib/ui/pages/more/more.dart create mode 100644 lib/ui/pages/settings/setting.dart diff --git a/assets/fonts/BrandIcons.ttf b/assets/fonts/BrandIcons.ttf index d902699b569c8bce53addec5a75d7ee129f1a1e8..3a5b43e2a751ceaff4fa6b9e63bbf05783419500 100644 GIT binary patch delta 440 zcmXv}T_{6g7=FK>%^V@KIj1REev&CJ{IsTa$0c#2lsPdLn=va>%37{mZGA3XxsVGt zIycn(-3sk$VlJe~Q7&9i^0Rpl`ReI?pXYs^_xrwh&v{R>V|B}^qycCrVr@FOJaw3V zIso8#0PB0euTIupSM3789ilscf~AX(V2>GS41}VwfmHDYfS?}+gW(Ca{oNJB{66y5 zkQ$pOF1W|Jg1mlC4f)Tk8>0a7EdW#I!;9t78h6VKfa4VnSE+P^*9HVzM0U@Aw~~iz{hL>q#mH~DJ^ zSVz?ewqeEfsB;)YF8wa1x>=X>N?j2V+Hb1Hxmldjf;b^2am>u6#;c7}EiT!Oq~k9Q zAl>0DymSRX%kT@U%eVm8EKT52AaaS*?vzUiIr3<<={u)+3QsiQ(S|h-k+n_P&4^88 Y9nF;3#g`*qA*qo_c*z&^PepOf57cjLq5uE@ delta 335 zcmX?O-e5k#px#A&nK}allK~KyrRP+pxpysk!@$6Dfq_BjOh#&AiuCo}j~Eyj9ssdf z22g;*lqDR<-UGxc8M!4D-YfrqU|?W;0_6MTSp)oAAc^{)W(HF6Ux3K+E*fchCF zfP96##N5 white.withOpacity(0.8); diff --git a/lib/config/brand_theme.dart b/lib/config/brand_theme.dart index 7c8458a3..0be8b325 100644 --- a/lib/config/brand_theme.dart +++ b/lib/config/brand_theme.dart @@ -18,4 +18,6 @@ final theme = ThemeData( ), ); -final brandPagePadding = EdgeInsets.symmetric(horizontal: 15, vertical: 30); +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 4a3c0c84..3a6a188b 100644 --- a/lib/config/text_themes.dart +++ b/lib/config/text_themes.dart @@ -23,6 +23,12 @@ final headline2Style = GoogleFonts.inter( color: BrandColors.headlineColor, ); +final headline3Style = GoogleFonts.inter( + fontSize: 20, + fontWeight: NamedFontWeight.extraBold, + color: BrandColors.headlineColor, +); + final captionStyle = GoogleFonts.inter( fontSize: 18, fontWeight: NamedFontWeight.medium, diff --git a/lib/ui/components/brand_divider/brand_divider.dart b/lib/ui/components/brand_divider/brand_divider.dart new file mode 100644 index 00000000..00bd0ebf --- /dev/null +++ b/lib/ui/components/brand_divider/brand_divider.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:selfprivacy/config/brand_colors.dart'; + +class BrandDivider extends StatelessWidget { + const BrandDivider({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: 1, + color: BrandColors.dividerColor, + ); + } +} + diff --git a/lib/ui/components/brand_header/brand_header.dart b/lib/ui/components/brand_header/brand_header.dart new file mode 100644 index 00000000..52a82010 --- /dev/null +++ b/lib/ui/components/brand_header/brand_header.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; +import 'package:selfprivacy/utils/extensions/text_extension.dart'; + +class BrandHeader extends StatelessWidget { + const BrandHeader({ + Key key, + @required this.title, + this.hasBackButton = false, + }) : super(key: key); + + final String title; + final bool hasBackButton; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only( + top: hasBackButton ? 4 : 17, + bottom: hasBackButton ? 7 : 20, + left: hasBackButton ? 1 : 15, + ), + child: Container( + child: Row( + children: [ + if (hasBackButton) ...[ + IconButton( + icon: Icon(BrandIcons.arrow_left), + onPressed: () => Navigator.of(context).pop(), + ), + SizedBox(width: 10), + ], + Text(title).caption, + ], + ), + ), + ); + } +} diff --git a/lib/ui/components/brand_icons/brand_icons.dart b/lib/ui/components/brand_icons/brand_icons.dart index 72be2f90..a6d3db1f 100644 --- a/lib/ui/components/brand_icons/brand_icons.dart +++ b/lib/ui/components/brand_icons/brand_icons.dart @@ -57,4 +57,6 @@ class BrandIcons { IconData(0xe816, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData github = IconData(0xe817, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData arrow_left = + IconData(0xe818, fontFamily: _kFontFam, fontPackage: _kFontPkg); } diff --git a/lib/ui/pages/about/about.dart b/lib/ui/pages/about/about.dart new file mode 100644 index 00000000..2c61ea0b --- /dev/null +++ b/lib/ui/pages/about/about.dart @@ -0,0 +1,56 @@ +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'; + +class AboutPage extends StatelessWidget { + const AboutPage({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + body: ListView( + children: [ + BrandHeader(title: 'О проекте', hasBackButton: true), + Padding( + padding: brandPagePadding2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + BrandDivider(), + SizedBox(height: 20), + Text('О проекте').h3, + SizedBox(height: 10), + Text('Всё больше организаций хотят владеть нашими данными') + .body1, + SizedBox(height: 10), + Text('А мы сами хотим распоряжаться своими данными на своем сервере.') + .body1, + SizedBox(height: 20), + BrandDivider(), + SizedBox(height: 10), + Text('Миссия проекта').h3, + SizedBox(height: 10), + Text( + 'Цифровая независимость и приватность доступная каждому'), + SizedBox(height: 20), + BrandDivider(), + SizedBox(height: 10), + Text('Цель').h3, + SizedBox(height: 10), + Text( + 'Развивать программу, которая позволит каждому создавать приватные сервисы для себя и своих близких'), + SizedBox(height: 10), + Text( + 'Развивать программу, которая позволит каждому создавать приватные сервисы для себя и своих близких'), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/ui/pages/info/info.dart b/lib/ui/pages/info/info.dart new file mode 100644 index 00000000..6a897995 --- /dev/null +++ b/lib/ui/pages/info/info.dart @@ -0,0 +1,46 @@ +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:package_info/package_info.dart'; + +class InfoPage extends StatelessWidget { + const InfoPage({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + body: ListView( + children: [ + BrandHeader(title: 'О приложении', hasBackButton: true), + Padding( + padding: brandPagePadding2, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + BrandDivider(), + SizedBox(height: 10), + FutureBuilder( + future: _version(), + builder: (context, snapshot) { + return Text( + 'Тут любая служебная информация, v.${snapshot.data}') + .body1; + }), + ], + ), + ), + ], + ), + ), + ); + } + + Future _version() async { + var packageInfo = await PackageInfo.fromPlatform(); + return packageInfo.version; + } +} diff --git a/lib/ui/pages/more/more.dart b/lib/ui/pages/more/more.dart new file mode 100644 index 00000000..2ded231c --- /dev/null +++ b/lib/ui/pages/more/more.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +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_icons/brand_icons.dart'; +import 'package:selfprivacy/ui/pages/about/about.dart'; +import 'package:selfprivacy/ui/pages/info/info.dart'; +import 'package:selfprivacy/ui/pages/settings/setting.dart'; +import 'package:selfprivacy/utils/extensions/text_extension.dart'; +import 'package:selfprivacy/utils/route_transitions/basic.dart'; + +class MorePage extends StatelessWidget { + const MorePage({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListView( + children: [ + BrandHeader(title: 'Еще'), + Padding( + padding: brandPagePadding2, + child: Column( + children: [ + BrandDivider(), + _NavItem( + title: 'Настройки', + iconData: BrandIcons.settings, + goTo: SettingsPage(), + ), + _NavItem( + title: 'О проекте Selfprivacy', + iconData: BrandIcons.triangle, + goTo: AboutPage(), + ), + _NavItem( + title: 'О приложении', + iconData: BrandIcons.help, + goTo: InfoPage(), + ), + ], + ), + ) + ], + ); + } +} + +class _NavItem extends StatelessWidget { + const _NavItem({ + Key key, + @required this.iconData, + @required this.goTo, + @required this.title, + }) : super(key: key); + + final IconData iconData; + final Widget goTo; + final String title; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => Navigator.of(context).push(materialRoute(goTo)), + child: Container( + padding: EdgeInsets.symmetric(vertical: 24), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1.0, + color: BrandColors.dividerColor, + ), + ), + ), + child: Row( + children: [ + Text(title).body1, + Spacer(), + Icon(iconData, size: 20), + SizedBox(width: 18), + ], + ), + ), + ); + } +} diff --git a/lib/ui/pages/onboarding/onboarding.dart b/lib/ui/pages/onboarding/onboarding.dart index 0838ba65..6b72eb7a 100644 --- a/lib/ui/pages/onboarding/onboarding.dart +++ b/lib/ui/pages/onboarding/onboarding.dart @@ -39,7 +39,8 @@ class OnboardingPage extends StatelessWidget { ), BrandButton.rised( onPressed: () { - Navigator.of(context).push(materialRoute(RootPage())); + Navigator.of(context) + .pushReplacement(materialRoute(RootPage())); }, title: 'Приступим!', ) diff --git a/lib/ui/pages/rootRoute.dart b/lib/ui/pages/rootRoute.dart index 0851c0d2..514b34fc 100644 --- a/lib/ui/pages/rootRoute.dart +++ b/lib/ui/pages/rootRoute.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:selfprivacy/ui/components/brand_tab_bar/brand_tab_bar.dart'; +import 'package:selfprivacy/ui/pages/more/more.dart'; import 'package:selfprivacy/ui/pages/servers/servers.dart'; import 'package:selfprivacy/ui/pages/services/services.dart'; @@ -37,7 +38,7 @@ class _RootPageState extends State ServersPage(), ServicesPage(), Text('users'), - Text('more'), + MorePage(), ], ), bottomNavigationBar: BottomTabBar( diff --git a/lib/ui/pages/servers/servers.dart b/lib/ui/pages/servers/servers.dart index 486106b7..dd182e25 100644 --- a/lib/ui/pages/servers/servers.dart +++ b/lib/ui/pages/servers/servers.dart @@ -16,7 +16,7 @@ class ServersPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( body: ListView( - padding: brandPagePadding, + padding: brandPagePadding1, children: [ Text('Начало').caption, Text('SelfPrivacy').h1, diff --git a/lib/ui/pages/services/services.dart b/lib/ui/pages/services/services.dart index a60f5a93..20e612c1 100644 --- a/lib/ui/pages/services/services.dart +++ b/lib/ui/pages/services/services.dart @@ -23,7 +23,7 @@ class _ServicesPageState extends State { final uninitialized = serviceCubit.state.uninitialized; return Scaffold( body: ListView( - padding: brandPagePadding, + padding: brandPagePadding1, children: [ Text('Сервисы').caption, SizedBox(height: 24), diff --git a/lib/ui/pages/settings/setting.dart b/lib/ui/pages/settings/setting.dart new file mode 100644 index 00000000..a5010edf --- /dev/null +++ b/lib/ui/pages/settings/setting.dart @@ -0,0 +1,165 @@ +import 'package:flutter/material.dart'; +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/utils/extensions/text_extension.dart'; + +class SettingsPage extends StatelessWidget { + const SettingsPage({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + body: ListView( + children: [ + BrandHeader(title: 'Настройки', hasBackButton: true), + Padding( + padding: brandPagePadding2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + BrandDivider(), + _SwitcherBlock( + child: _TextColumn( + title: 'Allow Auto-upgrade', + value: 'Wether to allow automatic packages upgrades', + ), + isActive: true, + ), + _SwitcherBlock( + child: _TextColumn( + title: 'Reboot after upgrade', + value: 'Reboot without prompt after applying updates', + ), + isActive: false, + ), + _Button( + onTap: () {}, + child: _TextColumn( + title: 'Server Timezone', + value: 'Europe/Kyiv', + ), + ), + _Button( + onTap: () {}, + child: _TextColumn( + title: 'Server Locale', + value: 'Default', + ), + ), + _Button( + onTap: () {}, + child: _TextColumn( + hasWarning: true, + title: 'Factory Reset', + value: 'Restore default settings on your server', + ), + ) + ], + ), + ) + ], + ), + ), + ); + } +} + +class _SwitcherBlock extends StatelessWidget { + const _SwitcherBlock({ + Key key, + @required this.child, + @required this.isActive, + }) : super(key: key); + + final Widget child; + final bool isActive; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 20, bottom: 5), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: BrandColors.dividerColor), + )), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible(child: child), + SizedBox(width: 5), + Switch( + activeColor: BrandColors.green1, + activeTrackColor: BrandColors.green2, + onChanged: (v) {}, + value: isActive, + ), + ], + ), + ); + } +} + +class _Button extends StatelessWidget { + const _Button({ + Key key, + @required this.onTap, + @required this.child, + }) : super(key: key); + + final Widget child; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Container( + padding: EdgeInsets.only(top: 20, bottom: 5), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: BrandColors.dividerColor), + )), + child: child, + ), + ); + } +} + +class _TextColumn extends StatelessWidget { + const _TextColumn({ + Key key, + @required this.title, + @required this.value, + this.hasWarning = false, + }) : super(key: key); + + final String title; + final String value; + final bool hasWarning; + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title).body1.copyWith( + 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)), + ], + ); + } +} diff --git a/lib/utils/extensions/text_extension.dart b/lib/utils/extensions/text_extension.dart index 98b02bda..7def4aec 100644 --- a/lib/utils/extensions/text_extension.dart +++ b/lib/utils/extensions/text_extension.dart @@ -7,6 +7,8 @@ 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); + Text get caption => copyWith(style: captionStyle); Text get body1 => copyWith(style: body1Style); diff --git a/pubspec.lock b/pubspec.lock index 998c80bf..69f3d6fe 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -210,6 +210,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.0.4" + package_info: + dependency: "direct main" + description: + name: package_info + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.3+2" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 58875a15..a774e87b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: selfprivacy description: selfprivacy.org publish_to: 'none' -version: 1.0.0+1 +version: 0.1.0+1 environment: sdk: ">=2.7.0 <3.0.0" @@ -14,6 +14,7 @@ dependencies: equatable: ^1.2.5 flutter_bloc: ^6.1.1 google_fonts: ^1.1.1 + package_info: ^0.4.3+2 provider: ^4.3.2+2 url_launcher: ^5.7.10