From 5f7e0b9869b984dfa3161c38b3dfebb165c76df1 Mon Sep 17 00:00:00 2001 From: RockerFlower Date: Tue, 8 Nov 2022 00:54:09 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Show=20followers=20and=20followings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/translations/languages/de.dart | 2 + lib/common/translations/languages/en_gb.dart | 2 + lib/common/translations/languages/en_us.dart | 2 + lib/common/translations/languages/es.dart | 2 + lib/common/translations/languages/fr.dart | 7 +- lib/common/translations/languages/ja.dart | 2 + lib/common/translations/languages/ko.dart | 2 + lib/common/translations/languages/ru.dart | 2 + lib/common/translations/languages/th.dart | 2 + lib/common/translations/languages/tr.dart | 2 + lib/common/translations/languages/uk.dart | 2 + lib/common/translations/languages/vi.dart | 2 + lib/common/translations/languages/zh_cn.dart | 2 + lib/common/translations/languages/zh_hk.dart | 2 + lib/common/translations/languages/zh_tw.dart | 2 + lib/common/translations/strings.dart | 4 + lib/di/service_locator.dart | 9 + lib/main.dart | 2 + lib/ui/pages/home/components/card.dart | 2 + lib/ui/pages/home/components/card.social.dart | 178 +++++++++++++++ .../home/components/dialog.followers.dart | 212 +++++++++++++++++ .../home/components/dialog.followings.dart | 213 ++++++++++++++++++ lib/ui/pages/home/controller.dart | 11 + .../pages/home/controllers/card.social.dart | 122 ++++++++++ lib/util/verification.dart | 8 +- 25 files changed, 793 insertions(+), 3 deletions(-) create mode 100644 lib/ui/pages/home/components/card.social.dart create mode 100644 lib/ui/pages/home/components/dialog.followers.dart create mode 100644 lib/ui/pages/home/components/dialog.followings.dart create mode 100644 lib/ui/pages/home/controllers/card.social.dart diff --git a/lib/common/translations/languages/de.dart b/lib/common/translations/languages/de.dart index 4690df2..f54b18f 100644 --- a/lib/common/translations/languages/de.dart +++ b/lib/common/translations/languages/de.dart @@ -24,6 +24,8 @@ class DeTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/en_gb.dart b/lib/common/translations/languages/en_gb.dart index 213641c..b46cce1 100644 --- a/lib/common/translations/languages/en_gb.dart +++ b/lib/common/translations/languages/en_gb.dart @@ -24,6 +24,8 @@ class EnGBTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/en_us.dart b/lib/common/translations/languages/en_us.dart index 76f75c6..b3be187 100644 --- a/lib/common/translations/languages/en_us.dart +++ b/lib/common/translations/languages/en_us.dart @@ -24,6 +24,8 @@ class EnUSTranslations { 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + Strings.followers: 'followers', + Strings.followings: 'followings', Strings.events: 'Events', Strings.poaps: 'POAPs', Strings.growth: 'growth', diff --git a/lib/common/translations/languages/es.dart b/lib/common/translations/languages/es.dart index b95378d..ad658a5 100644 --- a/lib/common/translations/languages/es.dart +++ b/lib/common/translations/languages/es.dart @@ -24,6 +24,8 @@ class ESTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/fr.dart b/lib/common/translations/languages/fr.dart index f64b1fc..73a5b65 100644 --- a/lib/common/translations/languages/fr.dart +++ b/lib/common/translations/languages/fr.dart @@ -24,6 +24,8 @@ class FRTranslations { 'Vous ne semblez pas avoir de POAP pour l\'instant. Mais il n\'est pas trop tard ! Vous pouvez découvrir les POAPs en créeant votre premier POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', Strings.events: 'Évènements', Strings.poaps: 'POAPs', Strings.growth: 'croissance', @@ -59,7 +61,8 @@ class FRTranslations { Strings.newTagHint: 'nouveau tag d\'évènement', /// Moments - Strings.momentsDesc: '''Votre collection de POAPs est votre identité numérique. + Strings.momentsDesc: + '''Votre collection de POAPs est votre identité numérique. Elle montre au monde qui vous êtes : où vous êtes allé, ce que vous avez accompli et qui vous avez rencontré. Moments est un moyen d'ajouter de la valeur à votre souvenir numérique en sauvegardant des instants de vie dans un POAP, pour toujours.''', Strings.uploadMoments: 'Publier des moments sur welook.io', @@ -67,7 +70,7 @@ class FRTranslations { /// GitPOAP Strings.gitPOAPDesc: '''Un GitPOAP est un POAP ordinaire (avec un petit extra) qui est frappé par la plateforme GitPOAP pour les contributions significatives apportées aux projets open source. - Les propriétaires de repos distribuent automatiquement des GitPOAPs à leurs contributeurs en reconnaissance du travail accompli.''', + Les propriétaires de repos distribuent automatiquement des GitPOAPs à leurs contributeurs en reconnaissance du travail accompli.''', Strings.gitPOAPStart: 'Contribuer à POAPin', /// Watchlist(Initial state) diff --git a/lib/common/translations/languages/ja.dart b/lib/common/translations/languages/ja.dart index 81fa868..a55ccf9 100644 --- a/lib/common/translations/languages/ja.dart +++ b/lib/common/translations/languages/ja.dart @@ -24,6 +24,8 @@ class JaTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/ko.dart b/lib/common/translations/languages/ko.dart index 14e7c41..9df5a70 100644 --- a/lib/common/translations/languages/ko.dart +++ b/lib/common/translations/languages/ko.dart @@ -24,6 +24,8 @@ class KoTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/ru.dart b/lib/common/translations/languages/ru.dart index fc0947e..4de02e5 100644 --- a/lib/common/translations/languages/ru.dart +++ b/lib/common/translations/languages/ru.dart @@ -24,6 +24,8 @@ class RuTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/th.dart b/lib/common/translations/languages/th.dart index 1d2f9c4..59b2541 100644 --- a/lib/common/translations/languages/th.dart +++ b/lib/common/translations/languages/th.dart @@ -24,6 +24,8 @@ class ThTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/tr.dart b/lib/common/translations/languages/tr.dart index 2efaf86..b20718f 100644 --- a/lib/common/translations/languages/tr.dart +++ b/lib/common/translations/languages/tr.dart @@ -24,6 +24,8 @@ class TrTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/uk.dart b/lib/common/translations/languages/uk.dart index e102340..8595352 100644 --- a/lib/common/translations/languages/uk.dart +++ b/lib/common/translations/languages/uk.dart @@ -24,6 +24,8 @@ class UkTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/vi.dart b/lib/common/translations/languages/vi.dart index 8187eac..05cbf1c 100644 --- a/lib/common/translations/languages/vi.dart +++ b/lib/common/translations/languages/vi.dart @@ -24,6 +24,8 @@ class ViTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/zh_cn.dart b/lib/common/translations/languages/zh_cn.dart index 8b9d768..0b9685c 100644 --- a/lib/common/translations/languages/zh_cn.dart +++ b/lib/common/translations/languages/zh_cn.dart @@ -24,6 +24,8 @@ class ZhCNTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/zh_hk.dart b/lib/common/translations/languages/zh_hk.dart index 75737dd..f7df551 100644 --- a/lib/common/translations/languages/zh_hk.dart +++ b/lib/common/translations/languages/zh_hk.dart @@ -24,6 +24,8 @@ class ZhHKTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/languages/zh_tw.dart b/lib/common/translations/languages/zh_tw.dart index d3a0e81..970e243 100644 --- a/lib/common/translations/languages/zh_tw.dart +++ b/lib/common/translations/languages/zh_tw.dart @@ -24,6 +24,8 @@ class ZhTWTranslations { // 'You don\'t appear to have any POAP right now.\nBut it\'s not too late!\n\nBegin learning about POAP by creating a POAP.', /// Home(available) + // Strings.followers: 'followers', + // Strings.followings: 'followings', // Strings.events: 'Events', // Strings.poaps: 'POAPs', // Strings.growth: 'growth', diff --git a/lib/common/translations/strings.dart b/lib/common/translations/strings.dart index 102c998..02d6d15 100644 --- a/lib/common/translations/strings.dart +++ b/lib/common/translations/strings.dart @@ -13,6 +13,8 @@ class Strings { static const noPOAP = 'no_poap'; + static const followers = 'followers'; + static const followings = 'followings'; static const events = 'events'; static const poaps = 'poaps'; static const growth = 'growth'; @@ -119,6 +121,8 @@ String get strInvalidAddress => Strings.invalidAddress.tr; String get strNoPOAP => Strings.noPOAP.tr; +String get strFollowers => Strings.followers.tr; +String get strFollowings => Strings.followings.tr; String get strEvents => Strings.events.tr; String get strPOAPs => Strings.poaps.tr; String get strGrowth => Strings.growth.tr; diff --git a/lib/di/service_locator.dart b/lib/di/service_locator.dart index 9843f45..8c45d47 100644 --- a/lib/di/service_locator.dart +++ b/lib/di/service_locator.dart @@ -1,14 +1,17 @@ import 'package:get_it/get_it.dart'; import 'package:poapin/data/network/api/gitpoap.dart'; import 'package:poapin/data/network/api/poap.dart'; +import 'package:poapin/data/network/api/poap_social.dart'; import 'package:poapin/data/network/api/poapin.dart'; import 'package:poapin/data/network/api/welook.dart'; import 'package:poapin/data/network/client/dio_gitpoap.dart'; import 'package:poapin/data/network/client/dio_poap.dart'; +import 'package:poapin/data/network/client/dio_poap_social.dart'; import 'package:poapin/data/network/client/dio_poapin.dart'; import 'package:poapin/data/network/client/dio_welook.dart'; import 'package:poapin/data/repository/gitpoap_repository.dart'; import 'package:poapin/data/repository/poap_repository.dart'; +import 'package:poapin/data/repository/poap_social_repository.dart'; import 'package:poapin/data/repository/poapin_repository.dart'; import 'package:poapin/data/repository/welook_repository.dart'; @@ -25,6 +28,12 @@ Future setupAPI() async { getIt.registerSingleton(POAPAPI(dioClient: getIt())); getIt.registerSingleton(POAPRepository(getIt.get())); + /// POAP Social API + getIt.registerSingleton(DioPOAPSocialClient()); + getIt.registerSingleton( + POAPSocialAPI(dioClient: getIt())); + getIt.registerSingleton(POAPSocialRepository(getIt.get())); + /// GitPOAP API getIt.registerSingleton(DioGitPOAPClient()); getIt.registerSingleton(GitPOAPApi(dioClient: getIt())); diff --git a/lib/main.dart b/lib/main.dart index 772fa90..9bc818e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -34,6 +34,7 @@ import 'package:poapin/ui/pages/gitpoaps/controller.dart'; import 'package:poapin/ui/pages/home/controller.dart'; import 'package:poapin/ui/pages/home/controller.filter.dart'; import 'package:poapin/ui/pages/home/controllers/card.moment.dart'; +import 'package:poapin/ui/pages/home/controllers/card.social.dart'; import 'package:poapin/ui/pages/me/controller.dart'; import 'package:poapin/ui/pages/moment/controller.dart'; import 'package:poapin/ui/pages/moments/controller.dart'; @@ -52,6 +53,7 @@ Future main() async { await Hive.initFlutter(); Get.lazyPut(() => AuthController()); Get.lazyPut(() => HomeController()); + Get.lazyPut(() => SocialCardController()); Get.lazyPut(() => MomentsCardController()); Get.lazyPut(() => MomentsController()); Get.lazyPut(() => MomentController()); diff --git a/lib/ui/pages/home/components/card.dart b/lib/ui/pages/home/components/card.dart index e9b477d..f726a88 100644 --- a/lib/ui/pages/home/components/card.dart +++ b/lib/ui/pages/home/components/card.dart @@ -5,6 +5,7 @@ import 'package:poapin/common/translations/strings.dart'; import 'package:poapin/ui/pages/home/components/card.gitpoap.dart'; import 'package:poapin/ui/pages/home/components/card.moment.dart'; import 'package:poapin/ui/pages/home/components/card.poap.dart'; +import 'package:poapin/ui/pages/home/components/card.social.dart'; import 'package:poapin/ui/pages/home/components/chart.dart'; import 'package:poapin/ui/pages/home/controller.dart'; @@ -31,6 +32,7 @@ class CollectionCard extends StatelessWidget { scrollDirection: Axis.horizontal, children: const [ POAPCard(), + SocialCard(), MomentCard(), GitPOAPCard(), ], diff --git a/lib/ui/pages/home/components/card.social.dart b/lib/ui/pages/home/components/card.social.dart new file mode 100644 index 0000000..d789ae5 --- /dev/null +++ b/lib/ui/pages/home/components/card.social.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:poapin/common/translations/strings.dart'; +import 'package:poapin/res/colors.dart'; +import 'package:poapin/ui/pages/home/controllers/card.social.dart'; + +class SocialCard extends StatelessWidget { + const SocialCard({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 100, + child: Card( + clipBehavior: Clip.antiAlias, + elevation: 16, + shape: const ContinuousRectangleBorder( + side: BorderSide(color: Colors.white70, width: 1), + borderRadius: BorderRadius.all(Radius.circular(24))), + shadowColor: Colors.black26, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: GetBuilder( + builder: (c) => RawMaterialButton( + elevation: 0, + highlightElevation: 0, + hoverElevation: 0, + onPressed: () { + c.showFollowersDialog(); + }, + fillColor: Colors.white, + child: Stack( + alignment: Alignment.center, + children: [ + Container(), + Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + alignment: Alignment.bottomCenter, + child: Text( + strFollowers, + style: GoogleFonts.shareTechMono( + color: Colors.black45, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + ), + ), + const SizedBox(height: 4), + Expanded( + child: Container( + alignment: Alignment.topCenter, + child: c.isLoadingFollowers + ? Container( + width: 12, + height: 12, + margin: const EdgeInsets.only(top: 8), + child: + const CircularProgressIndicator( + strokeWidth: 1, + color: Colors.indigo, + ), + ) + : FittedBox( + fit: BoxFit.scaleDown, + child: Text( + c.followersWithENS.length + .toString(), + maxLines: 1, + softWrap: false, + style: GoogleFonts.shareTechMono( + color: Colors.black87, + fontSize: 20, + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + Container( + height: 0.6, + width: double.infinity, + margin: const EdgeInsets.symmetric(horizontal: 8), + color: PColor.background, + ), + Expanded( + child: GetBuilder( + builder: (c) => RawMaterialButton( + elevation: 0, + highlightElevation: 0, + hoverElevation: 0, + onPressed: () { + c.showFollowingsDialog(); + }, + fillColor: Colors.white, + child: Stack( + alignment: Alignment.center, + children: [ + Container(), + Container( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + alignment: Alignment.bottomCenter, + child: Text( + strFollowings, + style: GoogleFonts.shareTechMono( + color: Colors.black45, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + ), + ), + const SizedBox(height: 4), + Expanded( + child: Container( + alignment: Alignment.topCenter, + child: c.isLoadingFollowings + ? Container( + width: 12, + height: 12, + margin: const EdgeInsets.only(top: 8), + child: + const CircularProgressIndicator( + strokeWidth: 1, + color: Colors.indigo, + ), + ) + : FittedBox( + fit: BoxFit.scaleDown, + child: Text( + c.followingsWithENS.length + .toString(), + maxLines: 1, + softWrap: false, + style: GoogleFonts.shareTechMono( + color: Colors.black87, + fontSize: 20, + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/ui/pages/home/components/dialog.followers.dart b/lib/ui/pages/home/components/dialog.followers.dart new file mode 100644 index 0000000..b6cef0e --- /dev/null +++ b/lib/ui/pages/home/components/dialog.followers.dart @@ -0,0 +1,212 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:poapin/common/translations/strings.dart'; +import 'package:poapin/res/colors.dart'; +import 'package:poapin/ui/pages/home/controllers/card.social.dart'; + +class FollowersDialog extends StatelessWidget { + const FollowersDialog({Key? key, required this.followers}) : super(key: key); + + final List> followers; + + Widget _buildFollwerItem(Map follower) { + return Card( + shape: ContinuousRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + color: Colors.white, + elevation: 0, + shadowColor: Colors.black26, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + child: Row( + children: [ + follower.values.first == '-' + ? SizedBox( + width: 12, + height: 12, + child: CircularProgressIndicator( + strokeWidth: 0.6, + valueColor: + AlwaysStoppedAnimation(Colors.indigo.shade300), + ), + ) + : follower.values.first == '' + ? Container() + : Text( + follower.values.first, + style: GoogleFonts.robotoMono( + color: Colors.black87, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + follower.values.first == '' + ? Container() + : const SizedBox( + width: 16, + ), + Expanded( + child: Text( + Get.find() + .getSimpleAddress(follower.keys.first), + overflow: TextOverflow.fade, + maxLines: 1, + softWrap: false, + textAlign: follower.values.first == '' + ? TextAlign.left + : TextAlign.end, + style: GoogleFonts.robotoMono( + color: follower.values.first == '' + ? Colors.black87 + : Colors.black38, + fontWeight: FontWeight.bold, + fontSize: follower.values.first == '' ? 14 : 10, + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildFollowersContent() { + return Container( + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 12), + child: ListView( + shrinkWrap: true, + children: [ + const SizedBox(height: 72), + ...followers.map((f) => _buildFollwerItem(f)), + const SizedBox(height: 40), + ], + ), + ); + } + + Widget _buildEmptyContent() { + return Container( + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 12), + child: ListView( + shrinkWrap: true, + children: [ + const SizedBox(height: 72), + Text( + 'You\'ll gain followers if your friends save your collection on the official POAP app! ', + style: GoogleFonts.roboto( + fontSize: 16, + height: 1.5, + ), + ), + const SizedBox(height: 32), + RawMaterialButton( + onPressed: () { + Get.find().launchPOAP(); + }, + shape: ContinuousRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + fillColor: PColor.primary, + elevation: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Text( + 'Go to POAP.xyz', + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white, + letterSpacing: 1.1, + ), + ), + ), + ), + const SizedBox(height: 8), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: Alignment.center, + child: Container( + margin: const EdgeInsets.only(left: 32, right: 32, bottom: 44, top: 32), + child: Material( + color: PColor.background, + shadowColor: Colors.black54, + elevation: 8, + shape: const ContinuousRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(56)), + side: BorderSide(color: Color(0xFFD2D2D2), width: 4), + ), + clipBehavior: Clip.antiAlias, + child: Container( + constraints: const BoxConstraints( + maxWidth: 300, minWidth: 280, minHeight: 128, maxHeight: 512), + child: Stack( + children: [ + GetBuilder(builder: (c) { + if (c.followersWithENS.isNotEmpty) { + return _buildFollowersContent(); + } else { + return _buildEmptyContent(); + } + }), + Container( + height: 56, + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Material( + elevation: 20, + shadowColor: Colors.black26, + shape: const ContinuousRectangleBorder( + borderRadius: + BorderRadius.vertical(bottom: Radius.circular(56)), + ), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 14), + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'icons/ic_poap.png', + package: 'web3_icons', + height: 24, + ), + const SizedBox(width: 8), + Text( + strFollowers, + style: GoogleFonts.robotoMono( + fontSize: 18, + fontWeight: FontWeight.w500, + color: PColor.primary), + ), + const SizedBox(width: 8), + Text( + '[${followers.length}]', + style: GoogleFonts.robotoMono( + fontSize: 18, + fontWeight: FontWeight.w500, + color: PColor.primary), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/ui/pages/home/components/dialog.followings.dart b/lib/ui/pages/home/components/dialog.followings.dart new file mode 100644 index 0000000..912cb9e --- /dev/null +++ b/lib/ui/pages/home/components/dialog.followings.dart @@ -0,0 +1,213 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:poapin/common/translations/strings.dart'; +import 'package:poapin/res/colors.dart'; +import 'package:poapin/ui/pages/home/controllers/card.social.dart'; + +class FollowingsDialog extends StatelessWidget { + const FollowingsDialog({Key? key, required this.followings}) + : super(key: key); + + final List> followings; + + Widget _buildFollingItem(Map follower) { + return Card( + shape: ContinuousRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + color: Colors.white, + elevation: 0, + shadowColor: Colors.black26, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + child: Row( + children: [ + follower.values.first == '-' + ? SizedBox( + width: 12, + height: 12, + child: CircularProgressIndicator( + strokeWidth: 0.6, + valueColor: + AlwaysStoppedAnimation(Colors.indigo.shade300), + ), + ) + : follower.values.first == '' + ? Container() + : Text( + follower.values.first, + style: GoogleFonts.robotoMono( + color: Colors.black87, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + ), + follower.values.first == '' + ? Container() + : const SizedBox( + width: 16, + ), + Expanded( + child: Text( + Get.find() + .getSimpleAddress(follower.keys.first), + overflow: TextOverflow.fade, + maxLines: 1, + softWrap: false, + textAlign: follower.values.first == '' + ? TextAlign.left + : TextAlign.end, + style: GoogleFonts.robotoMono( + color: follower.values.first == '' + ? Colors.black87 + : Colors.black38, + fontWeight: FontWeight.bold, + fontSize: follower.values.first == '' ? 14 : 10, + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildFollowingsContent() { + return Container( + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 12), + child: ListView( + shrinkWrap: true, + children: [ + const SizedBox(height: 72), + ...followings.map((f) => _buildFollingItem(f)), + const SizedBox(height: 40), + ], + ), + ); + } + + Widget _buildEmptyContent() { + return Container( + padding: const EdgeInsets.only(left: 16, right: 16, bottom: 12), + child: ListView( + shrinkWrap: true, + children: [ + const SizedBox(height: 72), + Text( + 'Save your friends\' collections on the official POAP app.', + style: GoogleFonts.roboto( + fontSize: 16, + height: 1.5, + ), + ), + const SizedBox(height: 32), + RawMaterialButton( + onPressed: () { + Get.find().launchPOAP(); + }, + shape: ContinuousRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + fillColor: PColor.primary, + elevation: 0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Text( + 'Go to POAP.xyz', + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white, + letterSpacing: 1.1, + ), + ), + ), + ), + const SizedBox(height: 8), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return Align( + alignment: Alignment.center, + child: Container( + margin: const EdgeInsets.only(left: 32, right: 32, bottom: 44, top: 32), + child: Material( + color: PColor.background, + shadowColor: Colors.black54, + elevation: 8, + shape: const ContinuousRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(56)), + side: BorderSide(color: Color(0xFFD2D2D2), width: 4), + ), + clipBehavior: Clip.antiAlias, + child: Container( + constraints: const BoxConstraints( + maxWidth: 300, minWidth: 280, minHeight: 128, maxHeight: 512), + child: Stack( + children: [ + GetBuilder(builder: (c) { + if (c.followingsWithENS.isNotEmpty) { + return _buildFollowingsContent(); + } else { + return _buildEmptyContent(); + } + }), + Container( + height: 56, + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Material( + elevation: 20, + shadowColor: Colors.black26, + shape: const ContinuousRectangleBorder( + borderRadius: + BorderRadius.vertical(bottom: Radius.circular(56)), + ), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 14), + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'icons/ic_poap.png', + package: 'web3_icons', + height: 24, + ), + const SizedBox(width: 8), + Text( + strFollowings, + style: GoogleFonts.robotoMono( + fontSize: 18, + fontWeight: FontWeight.w500, + color: PColor.primary), + ), + const SizedBox(width: 8), + Text( + '[${followings.length}]', + style: GoogleFonts.robotoMono( + fontSize: 18, + fontWeight: FontWeight.w500, + color: PColor.primary), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/ui/pages/home/controller.dart b/lib/ui/pages/home/controller.dart index 112139a..823b7fa 100644 --- a/lib/ui/pages/home/controller.dart +++ b/lib/ui/pages/home/controller.dart @@ -24,6 +24,7 @@ import 'package:poapin/data/models/token.dart'; import 'package:poapin/ui/pages/detail/dialog/addtag.dart'; import 'package:poapin/ui/pages/home/components/dialog.gitpoap.dart'; import 'package:poapin/ui/pages/home/controllers/card.moment.dart'; +import 'package:poapin/ui/pages/home/controllers/card.social.dart'; import 'package:poapin/util/verification.dart'; import 'package:web3dart/web3dart.dart'; import 'package:web_socket_channel/io.dart'; @@ -227,6 +228,8 @@ class HomeController extends BaseController { getCachedData(); getData(); getMoments(); + getFollowers(); + getFollowings(); getGitPOAPs(); _initWebMessage(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { @@ -894,6 +897,14 @@ class HomeController extends BaseController { Get.find().getFirstMoment(ethAddress); } + void getFollowers() { + Get.find().getFollowers(ethAddress); + } + + void getFollowings() { + Get.find().getFollowings(ethAddress); + } + void getGitPOAPs() { isLoadingGitPOAPs = true; update(); diff --git a/lib/ui/pages/home/controllers/card.social.dart b/lib/ui/pages/home/controllers/card.social.dart new file mode 100644 index 0000000..c68c86c --- /dev/null +++ b/lib/ui/pages/home/controllers/card.social.dart @@ -0,0 +1,122 @@ +import 'package:ens_dart/ens_dart.dart'; +import 'package:ethereum_addresses/ethereum_addresses.dart'; +import 'package:get/get.dart'; +import 'package:poapin/data/repository/poap_social_repository.dart'; +import 'package:poapin/di/service_locator.dart'; +import 'package:poapin/ui/controller.base.dart'; +import 'package:poapin/ui/pages/home/components/dialog.followers.dart'; +import 'package:poapin/ui/pages/home/components/dialog.followings.dart'; +import 'package:poapin/util/verification.dart'; +import 'package:web3dart/web3dart.dart'; +import 'package:web_socket_channel/io.dart'; +import 'package:http/http.dart'; + +class SocialCardController extends BaseController { + List> followersWithENS = []; + List> followingsWithENS = []; + bool isLoadingFollowers = true; + bool isLoadingFollowings = true; + bool isError = false; + + final poapSocialRepository = getIt.get(); + + @override + onInit() { + super.onInit(); + final client = Web3Client(rpcUrl, Client(), socketConnector: () { + return IOWebSocketChannel.connect(wsUrl).cast(); + }); + ens = Ens(client: client); + } + + getFollowers(String address) { + isLoadingFollowers = true; + followersWithENS = []; + update(); + poapSocialRepository.getFollowers(address).then( + (List response) async { + if (response.isNotEmpty) { + followersWithENS = initListWithENS(response); + } else { + followersWithENS = []; + } + isLoadingFollowers = false; + update(); + refreshENS(followersWithENS); + }, + ); + } + + getFollowings(String address) { + isLoadingFollowings = true; + followingsWithENS = []; + update(); + poapSocialRepository.getFollowings(address).then( + (List response) async { + if (response.isNotEmpty) { + followingsWithENS = initListWithENS(response); + } else { + followingsWithENS = []; + } + isLoadingFollowings = false; + update(); + refreshENS(followingsWithENS); + }, + ); + } + + List> initListWithENS(List ethList) { + return ethList.map((e) => {checksumEthereumAddress(e): '-'}).toList(); + } + + Future>> refreshENS( + List> addresses) async { + List> listWithENS = []; + for (var address in addresses) { + print(address); + try { + await VerificationHelper.getENSbyETH(ens, address.keys.first) + .then((ensName) { + address.update(address.keys.first, (value) => ensName); + }); + } catch (e) { + address.update(address.keys.first, (value) => ''); + } + } + update(); + return listWithENS; + } + + String getSimpleAddress(String address) { + if (address.contains('eth')) { + return address; + } + if (address.length > 18) { + return checksumEthereumAddress(address).substring(0, 10) + + '...' + + address.substring(address.length - 4); + } + return address; + } + + void showFollowersDialog() { + Get.dialog(FollowersDialog( + followers: followersWithENS, + )); + } + + void showFollowingsDialog() { + Get.dialog(FollowingsDialog( + followings: followingsWithENS, + )); + } + + void launchPOAP() { + launchURL('https://poap.xyz/'); + } + + @override + String screenName() { + return 'SocialCard'; + } +} diff --git a/lib/util/verification.dart b/lib/util/verification.dart index 82840c7..c70c437 100644 --- a/lib/util/verification.dart +++ b/lib/util/verification.dart @@ -31,7 +31,13 @@ class VerificationHelper { } static Future getENSbyETH(Ens client, String eth) { - return client.withAddress(eth).getName(); + Future ensName = Future.value(''); + try { + ensName = client.withAddress(eth).getName(); + return ensName; + } catch (e) { + return ensName; + } } static Future getETHbyENS(Ens client, String ens) {