mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-26 18:56:38 +00:00
update first page
This commit is contained in:
parent
cbd00e87d3
commit
b626b05a1a
13
.vscode/launch.json
vendored
Normal file
13
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "selfprivacy",
|
||||
"request": "launch",
|
||||
"type": "dart"
|
||||
}
|
||||
]
|
||||
}
|
BIN
assets/images/logos/aws.png
Normal file
BIN
assets/images/logos/aws.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/images/logos/cloudflare.png
Normal file
BIN
assets/images/logos/cloudflare.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/images/logos/hetzner.png
Normal file
BIN
assets/images/logos/hetzner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/images/logos/namecheap.png
Normal file
BIN
assets/images/logos/namecheap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -2,20 +2,26 @@ PODS:
|
|||
- Flutter (1.0.0)
|
||||
- path_provider (0.0.1):
|
||||
- Flutter
|
||||
- url_launcher (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
path_provider:
|
||||
:path: ".symlinks/plugins/path_provider/ios"
|
||||
url_launcher:
|
||||
:path: ".symlinks/plugins/url_launcher/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
|
||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
||||
|
||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||
|
||||
|
|
|
@ -15,11 +15,17 @@ class BrandColors {
|
|||
/// ![](https://www.colorhexa.com/fafafa.png)
|
||||
static const Color gray3 = Color(0xFFFAFAFA);
|
||||
|
||||
/// ![](https://www.colorhexa.com/DDDDDD.png)
|
||||
static const Color gray4 = Color(0xFFDDDDDD);
|
||||
|
||||
static const primary = blue;
|
||||
static const headlineColor = black;
|
||||
static const textColor = gray1;
|
||||
static const inactive = gray2;
|
||||
static const scaffoldBackground = gray3;
|
||||
static const inputInactive = gray4;
|
||||
|
||||
static const textColor1 = black;
|
||||
static const textColor2 = gray1;
|
||||
|
||||
static get navBackground => white.withOpacity(0.8);
|
||||
}
|
||||
|
|
7
lib/config/brand_shadow.dart
Normal file
7
lib/config/brand_shadow.dart
Normal file
|
@ -0,0 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
final shadow8 = BoxShadow(
|
||||
offset: Offset(0, 4),
|
||||
blurRadius: 8,
|
||||
color: Colors.black.withOpacity(.08),
|
||||
);
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:selfprivacy/utils/named_font_weight.dart';
|
||||
import 'package:selfprivacy/config/text_themes.dart';
|
||||
|
||||
import 'brand_colors.dart';
|
||||
|
||||
|
@ -10,24 +10,10 @@ var theme = ThemeData(
|
|||
scaffoldBackgroundColor: BrandColors.scaffoldBackground,
|
||||
textTheme: GoogleFonts.interTextTheme(
|
||||
TextTheme(
|
||||
headline1: TextStyle(
|
||||
fontSize: 40,
|
||||
fontWeight: NamedFontWeight.extraBold,
|
||||
color: BrandColors.headlineColor,
|
||||
),
|
||||
headline2: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: NamedFontWeight.extraBold,
|
||||
color: BrandColors.headlineColor,
|
||||
),
|
||||
caption: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: NamedFontWeight.medium,
|
||||
color: BrandColors.headlineColor),
|
||||
bodyText1: TextStyle(
|
||||
fontSize: 15,
|
||||
color: BrandColors.textColor,
|
||||
),
|
||||
headline1: headline1Style,
|
||||
headline2: headline2Style,
|
||||
caption: captionStyle,
|
||||
bodyText1: bodyText1Style,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
35
lib/config/text_themes.dart
Normal file
35
lib/config/text_themes.dart
Normal file
|
@ -0,0 +1,35 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:selfprivacy/utils/named_font_weight.dart';
|
||||
|
||||
import 'brand_colors.dart';
|
||||
|
||||
final defaultTextStyle = GoogleFonts.inter(
|
||||
textStyle: TextStyle(
|
||||
fontSize: 15,
|
||||
color: BrandColors.textColor1,
|
||||
),
|
||||
);
|
||||
|
||||
final headline1Style = GoogleFonts.inter(
|
||||
fontSize: 40,
|
||||
fontWeight: NamedFontWeight.extraBold,
|
||||
color: BrandColors.headlineColor,
|
||||
);
|
||||
|
||||
final headline2Style = GoogleFonts.inter(
|
||||
fontSize: 24,
|
||||
fontWeight: NamedFontWeight.extraBold,
|
||||
color: BrandColors.headlineColor,
|
||||
);
|
||||
|
||||
final captionStyle = GoogleFonts.inter(
|
||||
fontSize: 18,
|
||||
fontWeight: NamedFontWeight.medium,
|
||||
color: BrandColors.headlineColor,
|
||||
);
|
||||
|
||||
final bodyText1Style = defaultTextStyle;
|
||||
final body2TextStyle = defaultTextStyle.copyWith(
|
||||
color: BrandColors.textColor2,
|
||||
);
|
|
@ -11,6 +11,7 @@ void main() {
|
|||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle.light, // Manually changnig appbar color
|
||||
child: MaterialApp(
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:ui';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
|
||||
enum BrandButtonTypes { rised }
|
||||
enum BrandButtonTypes { rised, text }
|
||||
|
||||
class BrandButton extends StatelessWidget {
|
||||
const BrandButton({
|
||||
|
@ -19,8 +19,8 @@ class BrandButton extends StatelessWidget {
|
|||
|
||||
static rised({
|
||||
Key key,
|
||||
VoidCallback onPressed,
|
||||
String title,
|
||||
@required VoidCallback onPressed,
|
||||
@required String title,
|
||||
}) =>
|
||||
BrandButton(
|
||||
key: key,
|
||||
|
@ -29,6 +29,18 @@ class BrandButton extends StatelessWidget {
|
|||
type: BrandButtonTypes.rised,
|
||||
);
|
||||
|
||||
static text({
|
||||
Key key,
|
||||
@required VoidCallback onPressed,
|
||||
@required String title,
|
||||
}) =>
|
||||
BrandButton(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
title: title,
|
||||
type: BrandButtonTypes.text,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (type) {
|
||||
|
@ -37,6 +49,12 @@ class BrandButton extends StatelessWidget {
|
|||
title: title,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
case BrandButtonTypes.text:
|
||||
return _TextButton(
|
||||
title: title,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -73,7 +91,7 @@ class _RisedButton extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
color: BrandColors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
|
@ -84,3 +102,36 @@ class _RisedButton extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TextButton extends StatelessWidget {
|
||||
const _TextButton({
|
||||
Key key,
|
||||
this.onPressed,
|
||||
this.title,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback onPressed;
|
||||
final String title;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: Container(
|
||||
height: 48,
|
||||
width: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: BrandColors.blue,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
25
lib/ui/components/brand_card/brand_card.dart
Normal file
25
lib/ui/components/brand_card/brand_card.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
import 'package:selfprivacy/utils/extensions/elevation_extension.dart';
|
||||
|
||||
class BrandCard extends StatelessWidget {
|
||||
const BrandCard({Key key, this.child}) : super(key: key);
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(bottom: 30),
|
||||
decoration: BoxDecoration(
|
||||
color: BrandColors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
).ev8,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 15,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
41
lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart
Normal file
41
lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart
Normal file
|
@ -0,0 +1,41 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
|
||||
class BrandModalSheet extends StatelessWidget {
|
||||
const BrandModalSheet({
|
||||
Key key,
|
||||
this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget child;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 32, bottom: 6),
|
||||
child: Container(
|
||||
height: 4,
|
||||
width: 30,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
color: Color(0xFFE3E3E3).withOpacity(0.65),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
constraints: BoxConstraints(minHeight: 400),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||
color: BrandColors.white,
|
||||
),
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(vertical: 40, horizontal: 15),
|
||||
child: child,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
37
lib/ui/components/brand_span_button/brand_span_button.dart
Normal file
37
lib/ui/components/brand_span_button/brand_span_button.dart
Normal file
|
@ -0,0 +1,37 @@
|
|||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class BrandSpanButton extends TextSpan {
|
||||
BrandSpanButton({
|
||||
@required String text,
|
||||
@required VoidCallback onTap,
|
||||
TextStyle style,
|
||||
}) : assert(text != null),
|
||||
assert(onTap != null),
|
||||
super(
|
||||
recognizer: TapGestureRecognizer()..onTap = onTap,
|
||||
text: text,
|
||||
style: (style ?? TextStyle()).copyWith(color: BrandColors.blue),
|
||||
);
|
||||
|
||||
static link({
|
||||
@required String text,
|
||||
String urlString,
|
||||
TextStyle style,
|
||||
}) =>
|
||||
BrandSpanButton(
|
||||
text: text,
|
||||
style: style,
|
||||
onTap: () => _launchURL(urlString ?? text),
|
||||
);
|
||||
|
||||
static _launchURL(String link) async {
|
||||
if (await canLaunch(link)) {
|
||||
await launch(link);
|
||||
} else {
|
||||
throw 'Could not launch $link';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/pages/rootRoute.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
import 'package:selfprivacy/utils/extensions/text_extension.dart';
|
||||
|
||||
class OnboardingPage extends StatelessWidget {
|
||||
const OnboardingPage({Key key}) : super(key: key);
|
||||
|
@ -27,13 +28,11 @@ class OnboardingPage extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
'Онбординг',
|
||||
style: Theme.of(context).textTheme.headline1,
|
||||
),
|
||||
).h1,
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
'Тут рассказ на 1-2 слайда о том, что делает это приложение, какие твои проблемы решает и как (в общем чего ожидать от сервиса).',
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
).body2,
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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/servers/servers.dart';
|
||||
|
||||
class RootPage extends StatefulWidget {
|
||||
const RootPage({Key key}) : super(key: key);
|
||||
|
@ -32,10 +33,10 @@ class _RootPageState extends State<RootPage>
|
|||
body: TabBarView(
|
||||
controller: tabController,
|
||||
children: [
|
||||
Text('a'),
|
||||
Text('b'),
|
||||
Text('c'),
|
||||
Text('d'),
|
||||
ServersPage(),
|
||||
Text('services'),
|
||||
Text('users'),
|
||||
Text('more'),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: BottomTabBar(
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.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/utils/extensions/text_extension.dart';
|
||||
|
||||
class ServersPage extends StatelessWidget {
|
||||
const ServersPage({Key key}) : super(key: key);
|
||||
|
@ -7,8 +14,217 @@ class ServersPage extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
child: Text('aaa111'),
|
||||
child: ListView(
|
||||
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 30),
|
||||
children: [
|
||||
Text('Начало').caption,
|
||||
Text('SelfPrivacy').h1,
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text:
|
||||
'Для устойчивости и приватности требует много учёток. Полная инструкция на ',
|
||||
style: body2TextStyle,
|
||||
),
|
||||
BrandSpanButton.link(
|
||||
text: 'selfprivacy.org/start',
|
||||
urlString: 'https://selfprivacy.org/start',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 50),
|
||||
BrandCard(
|
||||
child: Column(
|
||||
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(
|
||||
hintText: 'Hetzner API Token',
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
BrandButton.text(
|
||||
onPressed: () => showModalBottomSheet<void>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (BuildContext context) {
|
||||
return BrandModalSheet(
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Как получить Hetzner API Token').h2,
|
||||
SizedBox(height: 20),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '1 Переходим по ссылке ',
|
||||
style: bodyText1Style,
|
||||
),
|
||||
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: bodyText1Style,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
title: 'Как получить API Token',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
BrandCard(
|
||||
child: Column(
|
||||
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: body2TextStyle,
|
||||
),
|
||||
BrandSpanButton.link(
|
||||
text: 'NameCheap',
|
||||
urlString: 'https://www.namecheap.com',
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' или у любого другого регистратора. После этого настройте его на DNS-сервер CloudFlare',
|
||||
style: body2TextStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_MockForm(
|
||||
hintText: 'Домен, например, selfprivacy.org',
|
||||
submitButtonText: 'Проверить DNS',
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
BrandButton.text(
|
||||
onPressed: () {},
|
||||
title: 'Как настроить DNS CloudFlare',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
BrandCard(
|
||||
child: Column(
|
||||
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(
|
||||
hintText: 'CloudFlare API Token',
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
BrandButton.text(
|
||||
onPressed: () {},
|
||||
title: 'Как получить API Token',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
BrandCard(
|
||||
child: Column(
|
||||
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(
|
||||
hintText: 'Amazon AWS Access Key',
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
BrandButton.text(
|
||||
onPressed: () {},
|
||||
title: 'Как получить API Token',
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MockForm extends StatelessWidget {
|
||||
const _MockForm({
|
||||
Key key,
|
||||
@required this.hintText,
|
||||
this.submitButtonText = 'Подключить',
|
||||
}) : super(key: key);
|
||||
|
||||
final String hintText;
|
||||
final String submitButtonText;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
TextField(
|
||||
style: TextStyle(fontSize: 15, height: 1.6),
|
||||
decoration: InputDecoration(
|
||||
hintText: hintText,
|
||||
contentPadding: EdgeInsets.all(16),
|
||||
border: InputBorder.none,
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
borderSide: BorderSide(color: BrandColors.inputInactive),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
borderSide: BorderSide(color: BrandColors.blue),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
BrandButton.rised(onPressed: () {}, title: submitButtonText),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
33
lib/utils/extensions/elevation_extension.dart
Normal file
33
lib/utils/extensions/elevation_extension.dart
Normal file
|
@ -0,0 +1,33 @@
|
|||
library elevation_extension;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:selfprivacy/config/brand_shadow.dart';
|
||||
|
||||
extension ElevationExtension on BoxDecoration {
|
||||
BoxDecoration get ev8 => copyWith(boxShadow: [shadow8]);
|
||||
|
||||
BoxDecoration copyWith({
|
||||
Color color,
|
||||
DecorationImage image,
|
||||
BoxBorder border,
|
||||
BorderRadiusGeometry borderRadius,
|
||||
List<BoxShadow> boxShadow,
|
||||
Gradient gradient,
|
||||
BlendMode backgroundBlendMode,
|
||||
BoxShape shape,
|
||||
}) {
|
||||
return BoxDecoration(
|
||||
color: color ?? this.color,
|
||||
image: image ?? this.image,
|
||||
border: border ?? this.border,
|
||||
borderRadius: borderRadius ?? this.borderRadius,
|
||||
boxShadow: this.boxShadow != null || boxShadow != null
|
||||
? [...this.boxShadow ?? [], ...boxShadow ?? []]
|
||||
: null,
|
||||
gradient: gradient ?? this.gradient,
|
||||
backgroundBlendMode: backgroundBlendMode ?? this.backgroundBlendMode,
|
||||
shape: shape ?? this.shape,
|
||||
);
|
||||
}
|
||||
}
|
43
lib/utils/extensions/text_extension.dart
Normal file
43
lib/utils/extensions/text_extension.dart
Normal file
|
@ -0,0 +1,43 @@
|
|||
library text_extension;
|
||||
|
||||
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 caption => copyWith(style: captionStyle);
|
||||
|
||||
Text get body2 => copyWith(style: body2TextStyle);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
49
pubspec.lock
49
pubspec.lock
|
@ -95,6 +95,11 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
google_fonts:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -261,6 +266,48 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.3"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.7.10"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+4"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+9"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.9"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.5+1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.1+3"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -284,4 +331,4 @@ packages:
|
|||
version: "0.1.2"
|
||||
sdks:
|
||||
dart: ">=2.10.0-110 <2.11.0"
|
||||
flutter: ">=1.17.0 <2.0.0"
|
||||
flutter: ">=1.22.0 <2.0.0"
|
||||
|
|
37
pubspec.yaml
37
pubspec.yaml
|
@ -1,6 +1,6 @@
|
|||
name: selfprivacy
|
||||
description: selfprivacy.org
|
||||
publish_to: 'none'
|
||||
publish_to: 'none'
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
|
@ -11,39 +11,16 @@ dependencies:
|
|||
sdk: flutter
|
||||
cupertino_icons: ^1.0.0
|
||||
google_fonts: ^1.1.1
|
||||
url_launcher: ^5.7.10
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
|
||||
assets:
|
||||
- assets/images/logos/
|
||||
fonts:
|
||||
- family: BrandIcons
|
||||
fonts:
|
||||
- asset: assets/fonts/BrandIcons.ttf
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- family: BrandIcons
|
||||
fonts:
|
||||
- asset: assets/fonts/BrandIcons.ttf
|
||||
|
|
Loading…
Reference in a new issue