diff --git a/threefold_connect/lib/features/dao page/data/get_dao_proposals.dart b/threefold_connect/lib/features/dao page/data/get_dao_proposals.dart new file mode 100644 index 0000000..26541bd --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/get_dao_proposals.dart @@ -0,0 +1,14 @@ +import 'package:tfchain_client/models/dao.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +Future?>> getProposals() async { + try { + final client = QueryClient("wss://tfchain.dev.grid.tf/ws"); + await client.connect(); + final proposals = await client.dao.get(); + await client.disconnect(); + return proposals; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} diff --git a/threefold_connect/lib/features/dao page/data/get_farms_list.dart b/threefold_connect/lib/features/dao page/data/get_farms_list.dart new file mode 100644 index 0000000..46d6fbb --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/get_farms_list.dart @@ -0,0 +1,15 @@ +import 'package:gridproxy_client/gridproxy_client.dart'; +import 'package:gridproxy_client/models/farms.dart'; +import 'package:threefold_connect/main.reflectable.dart'; + +Future> getMyFarms(int twinId) async { + try { + initializeReflectable(); + GridProxyClient client = GridProxyClient('https://gridproxy.dev.grid.tf/'); + final farms = + await client.farms.list(ListFarmsQueryParameters(twin_id: twinId)); + return farms; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} diff --git a/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart b/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart new file mode 100644 index 0000000..246e796 --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart @@ -0,0 +1,14 @@ +import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +Future getProposalVotes(String hash) async { + try { + final client = QueryClient("wss://tfchain.dev.grid.tf/ws"); + await client.connect(); + final votes = await client.dao.getProposalVotes(hash: hash); + await client.disconnect(); + return votes; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} diff --git a/threefold_connect/lib/features/dao page/data/vote.dart b/threefold_connect/lib/features/dao page/data/vote.dart new file mode 100644 index 0000000..87fa65f --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/vote.dart @@ -0,0 +1,18 @@ +import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +//TODO: mnemonic need to be changed with user mnemonic +const mnemonic = ""; + +Future vote(bool vote, String hash, int farmId) async { + try { + final client = Client("wss://tfchain.dev.grid.tf/ws", mnemonic, "sr25519"); + client.connect(); + final daoVotes = + await client.dao.vote(farmId: farmId, hash: hash, approve: vote); + await client.disconnect(); + return daoVotes; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart new file mode 100644 index 0000000..f0dcc04 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:tfchain_client/models/dao.dart'; +import 'package:threefold_connect/theme/theme.dart'; +import 'package:threefold_connect/widgets/app_bar.dart'; +import '../../data/get_dao_proposals.dart'; +import '../widgets/active_executable_widget.dart'; + +class DaoPage extends StatefulWidget { + const DaoPage({super.key}); + + @override + State createState() => _DaoPageState(); +} + +class _DaoPageState extends State { + List? activeList = []; + List? inactiveList = []; + + void setActiveList() async { + final proposals = await getProposals(); + setState(() { + activeList = proposals['activeProposals']; + inactiveList = proposals['inactiveProposals']; + }); + } + + @override + void initState() { + setActiveList(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: const MyAppBar(title: 'Dao'), + body: Column( + children: [ + PreferredSize( + preferredSize: const Size.fromHeight(50.0), + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: TabBar( + labelColor: Theme.of(context).colorScheme.primary, + indicatorColor: Theme.of(context).colorScheme.primary, + unselectedLabelColor: white, + dividerColor: Theme.of(context).scaffoldBackgroundColor, + tabs: const [ + Tab(text: 'Active'), + Tab(text: 'Executable'), + ], + ), + ), + ), + Expanded( + child: TabBarView( + children: [ + ActiveOrExecutableWidget(proposals: activeList), + ActiveOrExecutableWidget( + proposals: inactiveList, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart new file mode 100644 index 0000000..6191c8e --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; +import 'package:tfchain_client/models/dao.dart'; + +import '../../../../theme/theme.dart'; +import 'dao_card.dart'; + +class ActiveOrExecutableWidget extends StatefulWidget { + List? proposals; + ActiveOrExecutableWidget({super.key, required this.proposals}); + + @override + State createState() => + _ActiveOrExecutableWidgetState(); +} + +class _ActiveOrExecutableWidgetState extends State { + List? proposals = []; + + @override + void initState() { + proposals = widget.proposals; + super.initState(); + } + + @override + void didUpdateWidget(covariant ActiveOrExecutableWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.proposals != oldWidget.proposals) { + setState(() { + proposals = widget.proposals; + }); + } + } + + void search(String searchWord) { + setState(() { + final String filterText = searchWord.toLowerCase(); + if (searchWord == "") { + setState(() { + proposals = widget.proposals; + }); + } else if (widget.proposals != null) { + setState(() { + proposals = widget.proposals + ?.where((Proposal entry) => + entry.action.toLowerCase().contains(filterText)) + .toList(); + }); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(60.0), + child: Padding( + padding: const EdgeInsets.all(10), + child: SizedBox( + height: 40, + child: SearchBar( + onChanged: search, + trailing: const [ + Icon( + Icons.search, + color: grey, + ) + ], + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.secondary), + hintText: "Search by proposal description", + hintStyle: MaterialStateProperty.all( + TextStyle(color: grey, fontFamily: inter, fontSize: 14)), + textStyle: MaterialStateProperty.all( + TextStyle(color: grey, fontFamily: inter, fontSize: 14)), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + ), + ), + ), + ), + ), + ), + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: _buildDaoCardList(proposals) ?? + [const Text('No active proposal at the moment')], + ), + ), + ); + } +} + +List? _buildDaoCardList(List? list) { + return list?.map((item) { + return DaoCard( + proposal: item, + ); + }).toList(); +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart new file mode 100644 index 0000000..1b66158 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -0,0 +1,196 @@ +import 'package:flutter/material.dart'; +import 'package:tfchain_client/models/dao.dart'; +import 'package:threefold_connect/theme/theme.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../data/get_proposal_votes.dart'; +import 'show_result_dialog.dart'; +import 'vote_dialog.dart'; + +class DaoCard extends StatefulWidget { + final Proposal proposal; + + const DaoCard({ + required this.proposal, + super.key, + }); + + @override + State createState() => _DaoCardState(); +} + +class _DaoCardState extends State { + @override + void initState() { + super.initState(); + } + + Future _launchUrl() async { + if (widget.proposal.link != "") { + final Uri url = Uri.parse(widget.proposal.link); + if (!await launchUrl(url)) { + const SnackBar( + content: Text( + "Can't go to proposal at this moment please try again later"), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(10), + padding: const EdgeInsets.all(15), + color: Theme.of(context).colorScheme.secondary, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text( + widget.proposal.action, + style: TextStyle( + color: white, + fontFamily: interBold, + fontSize: 16, + ), + textAlign: TextAlign.start, + ), + ), + const Divider( + thickness: 2, + color: grey, + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text( + widget.proposal.description, + style: TextStyle( + color: white, + fontFamily: inter, + ), + textAlign: TextAlign.start, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: TextButton( + onPressed: _launchUrl, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(2), + ), + side: const BorderSide( + color: tertiaryColor, + ), + ), + child: SizedBox( + width: double.infinity, + child: Text( + 'Go to proposal', + style: TextStyle( + color: Theme.of(context).colorScheme.tertiary, + fontFamily: interBold, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + 'You can vote until :', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + textAlign: TextAlign.start, + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + widget.proposal.end.formatDateTime(), + style: TextStyle( + color: white, + fontFamily: inter, + ), + textAlign: TextAlign.start, + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + child: TextButton( + onPressed: () async { + final votes = await getProposalVotes(widget.proposal.hash); + // ignore: use_build_context_synchronously + showDialog( + context: context, + builder: (_) => ShowResultDialog( + totalVotes: votes.ayes.length + votes.nays.length, + noVotes: votes.nays.length, + yesVotes: votes.ayes.length, + threshold: votes.threshold, + )); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + backgroundColor: backgroundColor, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + 'Show result', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + ), + ), + TextButton( + onPressed: () { + showDialog( + context: context, + builder: (_) => VoteDialog( + proposal: widget.proposal, + )); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + backgroundColor: Theme.of(context).colorScheme.primary, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + 'Vote', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart new file mode 100644 index 0000000..754cfa3 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -0,0 +1,175 @@ +import 'package:flutter/material.dart'; +import 'package:threefold_connect/theme/theme.dart'; + +class ShowResultDialog extends StatefulWidget { + final int totalVotes; + final int noVotes; + final int yesVotes; + final int threshold; + const ShowResultDialog({ + required this.threshold, + required this.noVotes, + required this.yesVotes, + required this.totalVotes, + super.key, + }); + + @override + State createState() => _ShowResultDialogState(); +} + +class _ShowResultDialogState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _noAnimation; + late Animation _yesAnimation; + late Animation _animation; + + @override + void initState() { + _animationController = AnimationController( + duration: const Duration(seconds: 1), + vsync: this, + ); + + _noAnimation = Tween( + begin: 0.0, + end: widget.totalVotes != 0 + ? (widget.noVotes / widget.totalVotes * 1.0) + : 0, + ).animate(_animationController); + + _yesAnimation = Tween( + begin: 0.0, + end: widget.totalVotes != 0 + ? (widget.yesVotes / widget.totalVotes * 1.0) + : 0, + ).animate(_animationController); + + _animation = Tween( + begin: 0.0, + end: (widget.totalVotes / widget.threshold), + ).animate(_animationController); + + _animationController.forward(); + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + backgroundColor: secondaryColor, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Stack( + alignment: Alignment.center, + children: [ + AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return LinearProgressIndicator( + minHeight: 40, + value: _animation.value, + color: Theme.of(context).colorScheme.primary, + backgroundColor: backgroundColor, + borderRadius: const BorderRadius.all(Radius.circular(5)), + ); + }, + ), + Center( + child: Text( + 'threshold ${widget.totalVotes} / ${widget.threshold}', + style: TextStyle( + color: Colors.white, + fontFamily: inter, + fontSize: 14, + ), + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Yes', + style: TextStyle( + color: Colors.white, + fontFamily: interBold, + fontSize: 16, + ), + ), + Text( + widget.totalVotes == 0 + ? '0%' + : '${(widget.yesVotes / widget.totalVotes) * 100}%', + style: TextStyle( + color: Colors.white, + fontFamily: inter, + fontSize: 14, + ), + ), + ], + ), + const SizedBox(height: 5), + AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return LinearProgressIndicator( + value: _yesAnimation.value, + color: Theme.of(context).colorScheme.primary, + backgroundColor: grey, + ); + }, + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'No', + style: TextStyle( + color: Colors.white, + fontFamily: interBold, + fontSize: 16, + ), + ), + Text( + widget.totalVotes == 0 + ? '0%' + : '${widget.noVotes / widget.totalVotes * 100}%', + style: TextStyle( + color: Colors.white, + fontFamily: inter, + fontSize: 14, + ), + ), + ], + ), + const SizedBox(height: 5), + AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return LinearProgressIndicator( + value: _noAnimation.value, + color: darkred, + backgroundColor: grey, + ); + }, + ), + ]), + ), + ); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart new file mode 100644 index 0000000..fba2c11 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -0,0 +1,171 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:gridproxy_client/models/farms.dart'; +import 'package:tfchain_client/models/dao.dart'; + +import '../../../../theme/theme.dart'; +import '../../data/get_farms_list.dart'; +import '../../data/vote.dart'; + +class VoteDialog extends StatefulWidget { + final Proposal proposal; + const VoteDialog({ + required this.proposal, + super.key, + }); + + @override + State createState() => _VoteDialogState(); +} + +class _VoteDialogState extends State { + int? farmId; + List farms = []; + + void setFarms() async { + List farmsList = + await getMyFarms(0); //TODO: replace with actual twin id + setState(() { + farms = farmsList; + }); + } + + @override + void initState() { + setFarms(); + super.initState(); + } + + List> _buildDropdownMenuEntries(List farms) { + return farms.map((farm) { + return DropdownMenuEntry( + value: farm.farmID, + label: farm.name, + labelWidget: Text( + farm.name, + style: TextStyle(color: Colors.white, fontFamily: interBold), + ), + ); + }).toList(); + } + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + backgroundColor: secondaryColor, + child: Padding( + padding: const EdgeInsets.all(30), + child: Flex( + direction: Axis.vertical, + mainAxisSize: MainAxisSize.min, + children: [ + DropdownMenu( + menuHeight: MediaQuery.sizeOf(context).height * 0.3, + enableFilter: true, + width: MediaQuery.sizeOf(context).width * 0.55, + textStyle: + TextStyle(color: white, fontFamily: interBold, fontSize: 14), + trailingIcon: const Icon( + CupertinoIcons.chevron_down, + color: white, + size: 18, + ), + selectedTrailingIcon: const Icon( + CupertinoIcons.chevron_up, + color: white, + size: 18, + ), + inputDecorationTheme: const InputDecorationTheme( + filled: true, + fillColor: backgroundColor, + enabledBorder: UnderlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(4)), + borderSide: BorderSide( + color: secondaryColor, + width: 8.0, + ), + ), + contentPadding: EdgeInsets.only(right: 5, left: 15), + ), + menuStyle: MenuStyle( + backgroundColor: + MaterialStateProperty.all(backgroundColor), + surfaceTintColor: + MaterialStateProperty.all(Colors.transparent), + shape: MaterialStateProperty.all( + const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4)), + ), + ), + padding: MaterialStateProperty.all( + const EdgeInsets.only(right: 5, left: 15, bottom: 5)), + ), + label: Text( + 'Select Farm', + style: TextStyle( + color: white, fontFamily: interBold, fontSize: 14), + ), + dropdownMenuEntries: _buildDropdownMenuEntries(farms), + onSelected: (int? value) { + if (value != null) { + farmId = value; + } + }, + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + TextButton( + onPressed: () { + if (farmId != null) { + vote(true, widget.proposal.hash, farmId!); + } + Navigator.pop(context); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + backgroundColor: Theme.of(context).colorScheme.primary, + ), + child: Text( + 'Yes', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + TextButton( + onPressed: () { + if (farmId != null) { + vote(false, widget.proposal.hash, farmId!); + } + Navigator.pop(context); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + backgroundColor: backgroundColor, + ), + child: Text( + 'No', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/threefold_connect/lib/main.dart b/threefold_connect/lib/main.dart index e06c0c4..5edbd71 100644 --- a/threefold_connect/lib/main.dart +++ b/threefold_connect/lib/main.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/pages/dao_page.dart'; import 'package:threefold_connect/theme/theme.dart'; + void main() { runApp(const MyApp()); } @@ -7,101 +9,13 @@ void main() { class MyApp extends StatelessWidget { const MyApp({super.key}); - // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', - theme: threefoldTheme, - home: const MyHomePage(title: 'Flutter Demo Home Page'), + theme: threefoldTheme, + home: const DaoPage(), ); } } -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } -} diff --git a/threefold_connect/lib/theme/theme.dart b/threefold_connect/lib/theme/theme.dart index f92309c..54c014d 100644 --- a/threefold_connect/lib/theme/theme.dart +++ b/threefold_connect/lib/theme/theme.dart @@ -3,12 +3,14 @@ import 'package:google_fonts/google_fonts.dart'; // Colors const primaryColor = Color(0xFF1AA18F); -const secondryColor = Color(0xFF212121); -const teritaryColor = Color(0xFF74DDC3); +const secondaryColor = Color(0xFF212121); +const tertiaryColor = Color(0xFF74DDC3); const backgroundColor = Color(0xFF383434); const white = Color(0xFFFFFFFF); const darkred = Color(0xFFA11A1A); const grey = Color(0xFF818181); +const backgroundGrey = Color(0xFF323232); + // Fonts var poppins = GoogleFonts.poppins().fontFamily; @@ -32,8 +34,8 @@ ThemeData threefoldTheme = ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: backgroundColor, primary: primaryColor, - secondary: secondryColor, - tertiary: teritaryColor, + secondary: secondaryColor, + tertiary: tertiaryColor, surfaceTint: Colors.transparent, ), textTheme: const TextTheme(headlineMedium: TextStyle(color: white)), diff --git a/threefold_connect/lib/widgets/app_bar.dart b/threefold_connect/lib/widgets/app_bar.dart index d843bfe..04c6f35 100644 --- a/threefold_connect/lib/widgets/app_bar.dart +++ b/threefold_connect/lib/widgets/app_bar.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import '../theme/theme.dart'; + class MyAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; @@ -8,7 +10,10 @@ class MyAppBar extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return AppBar( - title: Text(title), + title: Text( + title, + style: TextStyle(fontFamily: interBold, fontSize: 16), + ), leading: IconButton( icon: const Icon(Icons.menu), onPressed: () {}, diff --git a/threefold_connect/pubspec.yaml b/threefold_connect/pubspec.yaml index aa8abf8..759acf3 100644 --- a/threefold_connect/pubspec.yaml +++ b/threefold_connect/pubspec.yaml @@ -30,12 +30,27 @@ environment: dependencies: flutter: sdk: flutter - + tfchain_client: + git: + url: https://github.com/codescalers/tfgrid-sdk-dart.git + ref: main + path: packages/tfchain_client/ # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 google_fonts: 6.1.0 + url_launcher: ^6.3.0 + gridproxy_client: + git: + url: https://github.com/codescalers/tfgrid-sdk-dart.git + ref: tfchain_gridproxy + path: packages/gridproxy_client/ + + +dependency_overrides: + meta: ^1.11.0 + dev_dependencies: