completer.complete(reply); - Problem while integrating Google Pay - flutter

I am trying to integrate Google Pay payments into my app, and I see no errors in my code, but the Google Pay button is not showing up, and every time I hot reload my app, VSCode shows me
completer.complete(reply); this line of code. There seems to be no answer anywhere to this. Full code is attached below.
import 'package:flutter/material.dart';
import 'package:pay/pay.dart';
class HomePage extends StatelessWidget {
HomePage({Key? key}) : super(key: key);
final _paymentItems = <PaymentItem>[];
void onGooglePayResult(paymentResult) {
// Send the resulting Google Pay token to your server / PSP
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Ramzan Donation Form"),
),
body: Center(
child: Column(
children: [
const Text("Please check below to pay!"),
Row(children: [
GooglePayButton(
width: 200,
height: 50,
paymentConfigurationAsset: 'assets/gpay.json',
paymentItems: _paymentItems,
style: GooglePayButtonStyle.black,
type: GooglePayButtonType.pay,
margin: const EdgeInsets.only(top: 15.0),
onPaymentResult: (data) {
print(data);
},
loadingIndicator: const Center(
child: CircularProgressIndicator(),
),
),
])
],
),
),
);
}
}
I have got gpay.json under assets too. I have compared my code with working code online, I just don't get what's wrong. Any help is appreciated, thank you!

Related

Flutter gif image glitch

I do not know how to correctly explain, but I'll try. On my auth page, at the top of it, I have a GIF logo (without repeat). So auth page works like this:
logo animation running (for around 3 seconds)
after 3 seconds all other content appears (thanks to delayed_display)
And all works fine. But if I logged in to the app, and press log out, I'm redirected back to the same login page (as expected), but GIF not playing again, and simply freezing on the first frame. I can assume it's probably because my GIF set up to not repeat and it cached in flutter??? But if it's cached, why do I see it at the beginning of the animation, but not the final frame???
Also not about how authentication works. I'm using GetX for state management. So basically all is moving around authUser observable from AuthenticationController, and I have a Wrapper page which checks if authUser is not null to show DashboardScreen, otherwise AuthScreen.
Here is the AuthScreen with the gif image itself:
class AuthScreen extends StatelessWidget {
AuthScreen({Key? key}) : super(key: key);
final AuthenticationController _authController =
Get.find<AuthenticationController>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: SafeArea(
child: Column(
children: [
Image.asset('assets/images/n2mu_animated_logo.gif'), <=== here is the GIF
DelayedDisplay(
delay: const Duration(seconds: 4),
child: Container(
margin: const EdgeInsets.only(top: 40, right: 20, left: 20),
child: Center(
child: Column(children: [
RichText(
text: const TextSpan(children: [
TextSpan(
text: 'Hey, let verify:',
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 22),
),
])),
Obx(() => AnimatedSwitcher(
duration: const Duration(microseconds: 300),
child: (_authController.verificationCodeSent.value ==
false)
? PhoneNumberWidget() <== widget to shop phone number input
: SmsVerificationWidget(), <== SMS verification widget
)),
])),
)),
],
),
)));
}
}
Found the solution, you should use evict() method of the AssetImage widget. Here is more info https://github.com/flutter/flutter/issues/51775#issuecomment-680997795

RenderFlex overflowed only on screen transition but no visual issues

First, let me start with I am new to Flutter and this is my first app.
I am running into an issue where I am getting the error:
════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by 24 pixels on the bottom.
The relevant error-causing widget was
Column
lib/widgets/home_screen_cta.dart:42
════════════════════════════════════════════════════════════════════════════════
For the 4 buttons on my home screen.
The weird part is the screen looks fine. No yellow and black bars or anything. This only happens when I transition from the login screen to the home screen. If I move around the app, this does not happen. I do notice it on another form once it is submitted (only for the first submission, not for any others). It also looks bad for the first animation but after that it looks fine.
I was wondering if I should just ignore this but it seems like that is a bad idea.
I have tried changing this to use many other options. This includes:
Changed between Expanded and Flexible
Tried using a container/SizedBox instead
Tried to find another solution for the CTA Item but couldn't find anything that would do this look
At this point, I understand it's a overflow issue but there are no indications of an overflow appearing in the app.
I am trying to make the app responsive in nature so I believe I am doing okay for that. This RenderFlex overflow issue is really puzzling. The fact I don't see the yellow/black bars in the app makes me think this is happening during a transition and I wonder if I should be concerned about it?
Is there a way to control these animations? I really do not like them and I feel it's the transition causing the overflow issue... I'm a bit lost on this.
My code:
Home Screen (HomeDashboard):
import 'package:flutter/material.dart';
import '../app/components/app_drawer.dart';
import '../app/components/app_bar.dart';
import '../lang/app_localizations.dart';
import '../widgets/clock_text.dart';
import '../widgets/home_screen_cta.dart';
import '../widgets/home_screen_dashboard.dart';
import '../widgets/logo_horizontal.dart';
class HomeDashboard extends StatelessWidget {
const HomeDashboard({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: FreshFlowAppBar.get(title: AppLocalizations.of(context)!.title),
drawer: const AppDrawer(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: const [
Flexible(
flex: 1,
fit: FlexFit.loose,
child: LogoHorizontal(),
),
Flexible(
flex: 1,
fit: FlexFit.loose,
child: ClockText(),
),
Flexible(
flex: 6,
fit: FlexFit.tight,
child: HomeScreenDashboard(),
),
Flexible(
flex: 1,
fit: FlexFit.tight,
child: HomeScreenCta(),
),
],
),
),
),
);
}
}
HomeScreenCta:
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:fresh_flow/services/user.service.dart';
import 'package:provider/provider.dart';
import '../lang/app_localizations.dart';
import '../screens/home/pre_op_entry.dart';
import '../screens/home/prod_entry.dart';
import '../screens/home/post_op_entry.dart';
import '../screens/home/downtime_entry.dart';
import '../services/pre-op.service.dart';
import '../utils/size_helpers.dart';
class HomeScreenCta extends StatefulWidget {
const HomeScreenCta({Key? key}) : super(key: key);
#override
State<HomeScreenCta> createState() => _HomeScreenCtaState();
}
class _HomeScreenCtaState extends State<HomeScreenCta> {
bool _isPreOpSetupCompleted = false;
/// Returns a Widget for the CTA item
Widget _getCtaItem(
BuildContext context,
String title,
IconData iconData,
String routeName,
bool isEnabled,
) {
return GestureDetector(
onTap: () {
if (isEnabled) {
Navigator.of(context).pushNamed(routeName);
}
},
child: Opacity(
opacity: isEnabled ? 1.0 : 0.4,
child: Column( // This is causing RenderFlex overflow issue
children: [
Icon(
iconData,
size: displayHeight(context) * .05,
),
const SizedBox(
height: displayHeight(context) * .03,
),
Text(
title,
style: TextStyle(
fontSize: displayWidth(context) * 0.03,
),
)
],
),
),
);
}
#override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
// Define services
final _preOpService = Provider.of<PreOpService>(
context,
listen: false, // No need to listen
);
final _userService = Provider.of<UserService>(
context,
listen: false, // No need to listen
);
_preOpService.init(_userService.getId()!);
// Only Pre-Op Entry is allowed until it is complete all others need to be disabled
if (_preOpService.hasCompletedFirstPreopOfTheDay()) {
setState(() {
_isPreOpSetupCompleted = true;
});
}
final _width =
(displayWidth(context) - MediaQuery.of(context).padding.left) *
0.24;
final _children = [
SizedBox(
width: _width,
child: _getCtaItem(
context,
l10n!.preOpEntry,
FontAwesome.wrench,
PreOpEntry.routeName,
true,
),
),
SizedBox(
width: _width,
child: _getCtaItem(
context,
l10n.prodEntry,
MaterialCommunityIcons.account_hard_hat,
ProdEntry.routeName,
_isPreOpSetupCompleted,
),
),
SizedBox(
width: _width,
child: _getCtaItem(
context,
l10n.postOpEntry,
Icons.task_alt,
PostOpEntry.routeName,
_isPreOpSetupCompleted,
),
),
SizedBox(
width: _width,
child: _getCtaItem(
context,
l10n.downtimeEntry,
Icons.flag_sharp,
DowntimeEntry.routeName,
_isPreOpSetupCompleted,
),
),
];
return Center(
child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
children: _children,
),
);
}
}

Why is the function not invoke

I am new to coding and to flutter but am attempting to build an app for scanning, creating database, and inventory. I have been attempting to use flutter_barcode_scanner to achieve this along with several others while looking at multiple videos and blogs but have become unsuccessful and am now I'm coming here for help.
Provided is the code that I'm currently attempting to write for it. At this point I've confused myself since I was recently trying to utilize scan_preview also as my goal is to implement the scanner as a stream in half or 1/3rd of the screen and having the rest of the screen as the result that is pulled from the database or to create a new item if no match.
I am looking for some assistance in how to implement the barcode scanner in the fashion where it streams in part of the screen and why I am getting these issues and how to fix them. I have attempted the fixes that androidstudio is providing me but it creates many more issues.
Am I going about this the correct way?
How do I use flutter_barcode_scanner to stream in only a portion of the screen?
Errors from AndroidStudio:
child: ScanMode.BARCODE( Error: The expression doesn't evaluate to a function, so it can't be invoked
Center(child: Text(barcode)) Error: Undefined name 'barcode'
'#ff6666', 'Cancel', true, ScanMode.BARCODE)! Error: This requires the 'non-nullable' language feature to be enabled
return Scaffold(
appBar: AppBar(
title: Text("Barcode Scanner"),
centerTitle: true,
),
body: Column(
children: [
SizedBox(
width: double.infinity,
height: height / 0.6,
child: ScanMode.BARCODE(
onScanResult: (result) {
debugPrint('scan result: $result');
setState(() {
_data = result;
});
},
),
),
SizedBox(height: 20),
Center(child: Text(barcode))
],
));
}
}
class ScannerHelper extends StatefulWidget {
#override
_ScannerHelperState createState() => _ScannerHelperState();
}
class _ScannerHelperState extends State<ScannerHelper> {
String _scanbarcode = 'Unknown';
#override
void initState() {
super.initState();
}
Future<void> startBarcodeScanStream() async {
FlutterBarcodeScanner.getBarcodeStreamReceiver(
'#ff6666', 'Cancel', true, ScanMode.BARCODE)!
.listen((barcode) => print(barcode));
}
//build - to resolve scanner issue
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Barcode scan')),
body: Builder(builder: (BuildContext context) {
return Container(
alignment: Alignment.center,
child: Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () => startBarcodeScanStream(),
child: Text('Start barcode scan stream')),
Text('Scan result : $_scanbarcode\n',
style: TextStyle(fontSize: 20))
]));
})));
}

Flutter - what is needed to reload a network image when URL doesn't change

I'm just starting to learn app development with Flutter.
I am trying to build an app for learning purposes that grabs an image from a website using their API to get a random image. The app displays the image, and has a button which is supposed to grab a new random image when pressed.
The problem is that the URL for the API doesn't change, so Flutter thinks the image is the same and doesn't download a new image. At least, that's what I think is going on.
The code is very basic. So far just showing an image and a button. I've tried various things, and was thinking imageCache.clear(); should do the job when the button is pushed, but nothing seems to work. I have also tried various tricks with resetting state and trying to navigate to the same page with named routes, but they all still show the same image (which is why I think it might be a caching issue). :shrug:
All of this is running from a single main.dart file.
import 'package:flutter/material.dart';
import 'package:transparent_image/transparent_image.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightGreen[50],
appBar: AppBar(
title: Text("Show Me The Lettuce",
style: TextStyle(color: Colors.white70)),
backgroundColor: Colors.green[900],
),
body: ShowLettuce(),
),
),
);
}
class ShowLettuce extends StatefulWidget {
#override
_ShowLettuceState createState() => _ShowLettuceState();
}
class _ShowLettuceState extends State<ShowLettuce> {
String url = 'https://source.unsplash.com/900x900/?lettuce';
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(80.0),
child: Center(child: CircularProgressIndicator()),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage, image: url),
),
],
),
SizedBox(
height: 20.0,
),
RaisedButton(
onPressed: () {
imageCache.clear();
print('button pressed.');
},
child: Text('Show Me A New Lettuce!'),
),
],
),
);
}
}
I've read through a lot of Flutter documentation, but I'm not yet at the point where I can interpret much of what they say into usable code (not sure where and how I'm supposed to plug it into my code, for example the imageCache documentation: https://api.flutter.dev/flutter/painting/ImageCache-class.html). It seems like this should be a really easy solution, but it is escaping me.
Any help is much appreciated.
I have solved you problem.
You must add for your code couple lines code:
as first - import:
import 'dart:math';
next - in class _ShowLettuceState after declared url variable:
var random = new Random();
and for finish - after click the button, namely in onPressed:
setState(() {
url = 'https://source.unsplash.com/900x900/?lettuce' + random.nextInt(100).toString();
});
I suggest you use this code :
String url = 'https://source.unsplash.com/900x900/?lettuce-${Random().nextInt(100)}';
This is inspired by #Captivity solution, but I add a - that makes it work.

Could not find the correct Provider

I'm new to using flutter and i was trying to implement a covid 19 tracker of cases in the world and i got this error when creating a custom widget to display number of cases , can anyone help me figure out the solution to this exactly as i have been trying to fix it for hours now.
This is the exception caught by the widgets library:
Error: Could not find the correct Provider above this NewCasesCard Widget
To fix, please:
Ensure the Provider is an ancestor to this NewCasesCard Widget
Provide types to Provider
Provide types to Consumer
Provide types to Provider.of()
Ensure the correct context is being used.
If none of these solutions work, please file a bug at:
https://github.com/rrousselGit/provider/issues
Here is the code:
import 'package:stay_safe/Providers/AppBrain.dart';
import 'package:stay_safe/utils/theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class NewCasesCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return getCard(context);
}
Widget getCard(context){
if (Provider.of<AppBrain>(context).isloading2)
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SpinKitPumpingHeart(color: AppTheme().kcolors[0],),
),
);
else {
final countryInfo = Provider.of<AppBrain>(context).countryStats['countrydata'][0];
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 0.5,
color: Colors.white70,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('New Cases Today',style: GoogleFonts.cabin(fontSize: 25),),
),
SizedBox(height: 8,),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
StatIcon(countryInfo['total_active_cases'], 'Active', AppTheme().kcolors[0]),
StatIcon(countryInfo['total_new_cases_today'], 'New Cases', AppTheme().kcolors[2]),
StatIcon(countryInfo['total_new_deaths_today'], 'Deaths', AppTheme().kcolors[1])
],),
)
],
),
),
);
}
}
}
Widget StatIcon(int count,String type,Color color){
return Column(
children: <Widget>[
Text(count.toString(),style: GoogleFonts.cabin(color: color,fontWeight: FontWeight.bold,fontSize: 20),),
Text(type,style: GoogleFonts.cabin(color: color,fontWeight: FontWeight.bold,fontSize: 20),),
],
);
}
The issue looks like you have created the AppBrain provider in a different part of your widget tree to NewCasesCard, so when NewCasesCard attempts to find the provider by searching the tree it cannot. You need to make sure that the AppBrain provider is above NewCasesCard somewhere in the widget tree. So for example in the screen that includes this widget you could have:
class NewCasesScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Provider<AppBrain>(
create: (_) => AppBrain(),
child: Scaffold(
body: ListView(
children: [
NewCasesCard(),
...
]
),
),
);
}
Alternatively you could initialise the provider at the top of your app since, from the name, it looks like it is used throughout. For this you could utilise the MultiProvider and have:
(Example taken from the package readme)
void main {
runApp(MultiProvider(
providers: [
Provider<AppBrain>(create: (_) => AppBrain()),
Provider<SomethingElse>(create: (_) => SomethingElse()),
],
child: MaterialApp(...),
));
}
This way you can be sure that the provider will always be found.