diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..201d6fc1 --- /dev/null +++ b/.vscode/launch.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/assets/images/logos/aws.png b/assets/images/logos/aws.png new file mode 100644 index 00000000..81d58839 Binary files /dev/null and b/assets/images/logos/aws.png differ diff --git a/assets/images/logos/cloudflare.png b/assets/images/logos/cloudflare.png new file mode 100644 index 00000000..2e6ca435 Binary files /dev/null and b/assets/images/logos/cloudflare.png differ diff --git a/assets/images/logos/hetzner.png b/assets/images/logos/hetzner.png new file mode 100644 index 00000000..76ad07da Binary files /dev/null and b/assets/images/logos/hetzner.png differ diff --git a/assets/images/logos/namecheap.png b/assets/images/logos/namecheap.png new file mode 100644 index 00000000..7e1c6744 Binary files /dev/null and b/assets/images/logos/namecheap.png differ diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ba085ac2..946bddab 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -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 diff --git a/lib/config/brand_colors.dart b/lib/config/brand_colors.dart index 5a30d4a9..028d5c2c 100644 --- a/lib/config/brand_colors.dart +++ b/lib/config/brand_colors.dart @@ -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); } diff --git a/lib/config/brand_shadow.dart b/lib/config/brand_shadow.dart new file mode 100644 index 00000000..39c97a64 --- /dev/null +++ b/lib/config/brand_shadow.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +final shadow8 = BoxShadow( + offset: Offset(0, 4), + blurRadius: 8, + color: Colors.black.withOpacity(.08), +); diff --git a/lib/config/brand_theme.dart b/lib/config/brand_theme.dart index 1a643c88..e08c09d1 100644 --- a/lib/config/brand_theme.dart +++ b/lib/config/brand_theme.dart @@ -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, ), ), ); diff --git a/lib/config/text_themes.dart b/lib/config/text_themes.dart new file mode 100644 index 00000000..a871d0e8 --- /dev/null +++ b/lib/config/text_themes.dart @@ -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, +); diff --git a/lib/main.dart b/lib/main.dart index 16fda33c..039713f7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,6 +11,7 @@ void main() { class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + return AnnotatedRegion( value: SystemUiOverlayStyle.light, // Manually changnig appbar color child: MaterialApp( diff --git a/lib/ui/components/brand_button/brand_button.dart b/lib/ui/components/brand_button/brand_button.dart index bb475669..273c04ce 100644 --- a/lib/ui/components/brand_button/brand_button.dart +++ b/lib/ui/components/brand_button/brand_button.dart @@ -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, + ), + ), + ), + ); + } +} diff --git a/lib/ui/components/brand_card/brand_card.dart b/lib/ui/components/brand_card/brand_card.dart new file mode 100644 index 00000000..67d741d0 --- /dev/null +++ b/lib/ui/components/brand_card/brand_card.dart @@ -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, + ); + } +} diff --git a/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart b/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart new file mode 100644 index 00000000..fb5ed468 --- /dev/null +++ b/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart @@ -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, + ), + ], + ), + ); + } +} diff --git a/lib/ui/components/brand_span_button/brand_span_button.dart b/lib/ui/components/brand_span_button/brand_span_button.dart new file mode 100644 index 00000000..ac7c53db --- /dev/null +++ b/lib/ui/components/brand_span_button/brand_span_button.dart @@ -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'; + } + } +} diff --git a/lib/ui/pages/onboarding/onboarding.dart b/lib/ui/pages/onboarding/onboarding.dart index e9eaabd5..0838ba65 100644 --- a/lib/ui/pages/onboarding/onboarding.dart +++ b/lib/ui/pages/onboarding/onboarding.dart @@ -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, ], ), ), diff --git a/lib/ui/pages/rootRoute.dart b/lib/ui/pages/rootRoute.dart index dbaea3d6..a7cfaa82 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/servers/servers.dart'; class RootPage extends StatefulWidget { const RootPage({Key key}) : super(key: key); @@ -32,10 +33,10 @@ class _RootPageState extends State body: TabBarView( controller: tabController, children: [ - Text('a'), - Text('b'), - Text('c'), - Text('d'), + ServersPage(), + Text('services'), + Text('users'), + Text('more'), ], ), bottomNavigationBar: BottomTabBar( diff --git a/lib/ui/pages/servers/servers.dart b/lib/ui/pages/servers/servers.dart index c3be1224..924ba6b3 100644 --- a/lib/ui/pages/servers/servers.dart +++ b/lib/ui/pages/servers/servers.dart @@ -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( + 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), + ], + ); + } +} diff --git a/lib/utils/extensions/elevation_extension.dart b/lib/utils/extensions/elevation_extension.dart new file mode 100644 index 00000000..5732c8f9 --- /dev/null +++ b/lib/utils/extensions/elevation_extension.dart @@ -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, + 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, + ); + } +} diff --git a/lib/utils/extensions/text_extension.dart b/lib/utils/extensions/text_extension.dart new file mode 100644 index 00000000..6094bcf4 --- /dev/null +++ b/lib/utils/extensions/text_extension.dart @@ -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); + } +} diff --git a/pubspec.lock b/pubspec.lock index 86032e81..3a94cdcc 100644 --- a/pubspec.lock +++ b/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" diff --git a/pubspec.yaml b/pubspec.yaml index ed8d9c0d..ec9ecece 100644 --- a/pubspec.yaml +++ b/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