Flutter Web stream asyncMap is not calling - flutter

I am trying to calling this function from Stream builder on Mobile version(Android & IOS) it's working properly but in web asyncMap function is not working, please, what would be the possible reason behind it or is there any alternative to this?
Stream<_TalentDetailsViewModel> getViewModelStream(
BuildContext context, String matchId) {
final talents = Provider.of<Talents>(context, listen: false);
print("Printing properly");
return Provider.of<Matches>(context, listen: false)
.getStreamById(matchId).asyncMap((Match? match) async {
print("Not Printing");
final talent = await talents.getById(match!.talent!);
return _TalentDetailsViewModel(match, talent!);
});
}

Related

How to extract values from onCall firebase function and load them in future builder

i have a onCall cloud function which is returning
resp.status(200).send(JSON.stringify(entities));
In my flutter app, i have created this future to get values from it.
Future<void> dataDriven(String filename) async {
HttpsCallable callable =
FirebaseFunctions.instance.httpsCallable('fruitsType');
final results = await callable;
final datE = results.call(<String, dynamic>{
'filename': 'filename',
});
final dataF = await datE.then((value) => value.data);
print (dataF);
}
It is successfully printing the response which is as per expectation. but my snapshot is always returning null. It is not even reaching hasData stage. Please help.
Response;
[{"name":"banana","type":"fruit","count":0,"color":"yellow"},{{"name":"apple","type":"fruit","count":2,"color":"red"}]
FutureBuilder(
future: dataDriven('fruits.txt'),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: Text('An error has occurred!'),
);
} else {
final data = snapshot.data;
return Text(data.toString());
}
It looks like there are some issues that need to be fixed (See comments in code).
// Set the correct return type (not void because you are returning data)
Future<String> dataDriven(String filename) async {
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('fruitsType');
// You can just call the function here with await
final result = await callable.call({
// Remove the quotes on the filename value
'filename': filename,
});
// Don't forget to return the data
return result;
}
I suggest reading up on the documentation about calling cloud functions from a flutter app and basic dart syntax.

Flutter incoming video/audio call notification using Agora

I have been working on an application and I need to implement in app audio and video calling in my app which I have done using Agora.io but the issue is I have to display incoming call notification does not matter if app is in foreground or in background. I have tried many things but still I am unable to configure that out. I am using agora_rtc_engine package for making calls.
Any help would be appreciated.
Thanks
The code I am working with currently:
Call Methods
class CallMethods {
final callRef = FirebaseFirestore.instance.collection('Calls');
Stream<DocumentSnapshot> callstream({#required String id}) =>
callRef.doc(id).snapshots();
Future<bool> makeCall({#required Call call}) async {
try {
log('Making call');
call.hasdialed = true;
Map<String, dynamic> hasDialedMap = call.toMap(call);
call.hasdialed = false;
Map<String, dynamic> hasNotDialedMap = call.toMap(call);
await callRef.doc(call.senderid).set(hasDialedMap);
await callRef.doc(call.receiverid).set(hasNotDialedMap);
return true;
} catch (e) {
print(e);
return false;
}
}
Future<bool> endCall({#required Call call}) async {
try {
log('ending call');
await callRef.doc(call.senderid).delete();
await callRef.doc(call.receiverid).delete();
return true;
} catch (e) {
print(e);
return false;
}
}
}
Call Utils: Which is used to make calls
class CallUtils {
static final CallMethods callmethods = CallMethods();
static dial(
BuildContext context, {
#required User from,
#required var to,
}) async {
Call call = Call(
senderid: from.id,
// senderpic: from.avatar.url,
callername: from.name,
receiverid: to.id,
// receiverpic: to.avatar.url,
receivername: to.name,
channelid: Random().nextInt(999999).toString(),
);
bool callmade = await callmethods.makeCall(call: call);
call.hasdialed = true;
if (callmade) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VideoCallScreen(call: call),
),
);
}
}
}
After that I have a pickup layout which is used to wrap all the screens to display incoming call notification.
Pickup Call Layout:
(user.value.id != null)
? StreamBuilder<DocumentSnapshot>(
stream: callmethods.callstream(id: user.value.id),
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data.data() != null) {
Call call = Call.fromMap(snapshot.data.data());
if (!call.hasdialed) {
return PickupScreen(call: call);
} else {
return widget.scaffold;
}
} else {
return widget.scaffold;
}
},
)
: widget.scaffold,
It can be done via firebase push notifications & backend API service.
Sender side:
As soon as a call is made, you would post your backend api service with caller and receiver id, and your backend service is further responsible to send a push notification with a payload to the receiver.
Receiver side:
When receiver gets a push notification, you can configure it to open your app automatically and show a screen with all the payload information. Maybe you can show him a screen with accept and decline button and if he accepts, you can connect him to Agora.
Check this for payload configuration.

When I am using the provider package in Flutter to load data from an API into a list it repeatedly calls the API, how do I fix it?

I am trying to lode data from an api call that retrieves a map, I am able to get the map from the api to display how I want it to, however it repeatedly calls the api meaning the list keeps on refreshing. Even though I have tried setting the listener to false, it works but I have to manually refresh the app for it to work?
Additional Info: Assigning and Retrieving Data
import 'package:http/http.dart' as http;
class Stores with ChangeNotifier {
var s_length;
Future<List<Store>> getStores(String storeCatName) async {
final queryParameters = {
"store_category_name": storeCatName,
};
try {
//TODO this is the issue - must fix.
final uri = Uri.http("url", 'url', queryParameters);
//print(uri);
final response = await http.get(uri);
//print(response.statusCode);
//print(response.body);
if (response.statusCode == 200) {
final List<Store> stores = storeFromJson(response.body);
_stores = stores;
//print(_stores);
print("lenght: ${_stores.length}");
Store store;
for(store in _stores) {
store.products = Products().products(store.storeId);
}
//check if this is correct
notifyListeners();
//return stores;
} else {
print("error1");
return List<Store>();
}
} catch (e) {
print(e.toString());
return List<Store>();
}
//notifyListeners();
print(_stores);
}
List<Store> get favoriteItems {
//return _stores.where((storeItem) => storeItem.isFavorite).toList();
}
bool isNotFull(){
if (_stores.isEmpty){
return true;
} else {
return false;
}
}
int get numberOfStores{
return s_length;
}
List<Store> _stores = [];
List<Store> stores (String storeCatName){
getStores(storeCatName);
//print("cpp; + $s_length");
//notifyListeners();
return _stores;
}
}
final storesProvider = Provider.of<Stores>(
context, listen: false
);
storesProvider.getStores(categoryName);
final providerStoreList = storesProvider.stores(category.storeCategoryName);
Additional Info: Builder for List:
child: ListView.builder(
itemCount: providerStoreList.length,
itemBuilder: (context, index) => ChangeNotifierProvider.value(
value: providerStoreList[index],
child: StoreItem(),
)));
If any additional information is required just let me know. Any help would be greatly appreciated.
Thanks
Use
listen: false;
var ourClient = Provider.of<CartBlock>(context, listen: false);
Setting the listener to false means that your widget won't build again when notifyListeners() is called.
So, that might not be the issue.
The only reason I can think of is calling the API again from the build method,
which might happen if you are using a ListView builder.
So, every time you might be scrolling the ListView your API would call again.

Provider keeps data after logout

In my first screen, I consume data from Firebase and store it in provider.
This data will be used in another screen.
#override
void initState() {
super.initState();
FirestorePreviousPage.documentsListDescending().then((query) {
final totalHisabProvider = Provider.of<TotalHisab>(context, listen: false);
totalHisabProvider.addItemsFromSnapshot(query);
final unpaidHisabProvider = Provider.of<UnpaidHisab>(context, listen: false);
unpaidHisabProvider.addItems(query);
final paidHisabProvider = Provider.of<PaidHisab>(context, listen: false);
paidHisabProvider.addItems(query);
});
}
The documentsListAscending method:
static Future<QuerySnapshot> documentsListDescending() async {
final user = await CurrentUser.getCurrentUser();
return await Firestore.instance
.collection(user.uid)
.orderBy('serverTimestamp', descending: true)
.getDocuments();
}
My logout method:
static Future<void> logout(BuildContext context) async {
await FirebaseAuth.instance.signOut();
Navigator.of(context).pushNamedAndRemoveUntil(
WelcomeScreen.routeName,
(Route<dynamic> route) => false,
);
}
Now when I do logout and login with a different user, this new user still has access to the data of the previous user. Now I think I understand this part. As long as the app is working, it will keep the data in the state management.
But why doesn't the retrieve the new data from Firebase?
Shouldn't this line update data with the new user ID: .collection(user.uid)
I have an idea of how to solve this. Just clear the data in all the providers in the logout method. But that doesn't feel right. I need to understand why it isn't working first.
I ended up clearing the providers manually:
static Future<void> logout(BuildContext context) async {
await FirebaseAuth.instance.signOut();
// Clear all providers
Provider.of<Cart>(context, listen: false).clear();
Provider.of<UnpaidHisab>(context, listen: false).clear();
Provider.of<PaidHisab>(context, listen: false).clear();
Provider.of<TotalHisab>(context, listen: false).clear();
Navigator.of(context).pushNamedAndRemoveUntil(
WelcomeScreen.routeName,
(Route<dynamic> route) => false,
);
}
It works just fine as far I can tell.

Instance of 'Future<dynamic>' Flutter

I am trying to pass the Json data to the next screen after login.
Get Instance of 'Future' Flutter is displaying in print statement
onPressed()
var Data = getData(Username,Password);
print(Data);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ActivePage(jsondata:Data);
},
));
getData() print the exact json response
getData(username,password) async {
Auth auth = Auth();
var Data = await auth.signup(username, password);
print(Data);
}
Change your getData method to given code below:
getData(username,password) async {
Auth auth = Auth();
var Data = await auth.signup(username, password);
print(Data);
return Data;
}
As I can see, looks like you forget to return Data from getData method.