graphql-flutter subscriptions in flutter connectivity issue - flutter

I am new to flutter development but I have good experience in nodejs and graphql. I am trying to consume the subscription widget of graphql-flutter and update the changes. but the connection is not being established. But I could use the query and Mutation widget and get the results. The examples provided by the graphql-flutter team is 2 years old and same with https://hasura.io/ documents. Can someone help me providing the latest examples or samples.
graphql-flutter:^5.0.0
If additional infos needed please comment below.
Thanks in advance

I made a class that I use with graphql but it'll be able to work with graphql-flutter but passing the client to
return GraphQLProvider(
client: Services().graphQL.client, // just how I have my services set up
child: MaterialApp(
title: 'Flutter Demo',
...
),
);
class:
class GraphQL {
static final HttpLink _httpLink = HttpLink(environment[envMode]!['server']);
static WebSocketLink _wsLink(String token) => WebSocketLink(
environment[envMode]!['webSocket'],
config: SocketClientConfig(
inactivityTimeout: const Duration(hours: 1),
initialPayload: {
'Authorization': 'Bearer $token',
},
),
);
Link _splitLink(String token) => Link.split(
(request) => request.isSubscription,
_wsLink(token),
_httpLink,
);
GraphQLClient client(String token) {
return GraphQLClient(
link: AuthLink(getToken: () async => 'Bearer $token')
.concat(_splitLink(token)),
cache: GraphQLCache(
store: HiveStore(),
),
);
}
Future<void> initHive() async {
return await initHiveForFlutter();
}
}
The environment and envMode come from a config file that has gets its data from an env file to keep manage env and secrets.

Related

The generated token with vdomah JWT plugin in october cms is not accepted by the route with flutter

Hello i'm using flutter and i built an api with october cms.
I used the plugin by vdomah for the JWT Authentication, i think i followed the README.md but when i try to send the token to the api, i think is not accepted, the code:
the route:
Route::post('storephoto', function (Work $Work, Request $request) {
...
$Work->save();
})->middleware('Tymon\JWTAuth\Middleware\GetUserFromToken');
the flutter side:
upload(String fileName) {
http.post(AppUrl.baseURL + "/storephoto",
headers: {
'Authorization': 'Bearer $token'
},
body: {
"name": workNameController.text,
"images": fileName,
"description": descriptionController.text
}).then((result) {
setStatus(result.statusCode == 200 ? result.body : errMessage);
if(result.statusCode == 200) {
Navigator.push(context,
MaterialPageRoute(
builder: (context) => MainScreen()));
};
}).catchError((error) {
setStatus(error);
});
}
I printed the token in this function, and it exists, but i can't see the error in console.
I tried to make a GET route and the api seems to work in the browser, the message:
{
"error": "token_not_provided"
}
Now i think the token generated is not signed, or not recognized, how i can do?
Thanks in advance.
Once I faced the same issue, not sure there is some issue in the plugin, and doing the below change solved it.
plugins/vdomah/jwtauth/Plugin.php in this file do below change.
if you have any doubts please comment.
and can you use middleware like this
Route::group(['middleware' =>
['\Tymon\JWTAuth\Middleware\GetUserFromToken']], function() {
Route::post('storephoto', function (Request $request) {
//..code
});
});
as if I do like this its working

Service Worker not working when hosted, but works on localhost

I'm working on a PWA and I'm facing an issue with the service worker and I can't figure out what's wrong.
So when I run the lighthouse audit on localhost, it passes every criteria except for the HTTPS one. You can view it below;
However, when I publish the code to my github pages, and run the same audit there, the service worker is never activated. It gives me the error. The status becomes 'redundant' when I run the audit online.
Link: https://ibr4h1m.github.io/MAD5/index.html
Below I'll show the code, which is the exact same on the website that I've mentioned above.
main.js:
//Simple ServiceWorker
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js');
};
sw.js
const cacheName = 'tourguide-site';
const appShellFiles = ['index.html',
'help.html',
'destinations.html',
'contact.html',
'js/main.js',
'css/style.css',
'sw.js'
];
self.addEventListener('install', (e) => {
console.log('[Service Worker] Install');
e.waitUntil((async () => {
const cache = await caches.open(cacheName);
console.log('[Service Worker] Caching all: app shell and content');
await cache.addAll(appShellFiles);
})());
});
// Simple Activate since the other one is BS
self.addEventListener('activate', function () {
console.log('SW Activated');
});
self.addEventListener('fetch', (e) => {
e.respondWith((async () => {
const r = await caches.match(e.request);
console.log(`[Service Worker] Fetching resource: ${e.request.url}`);
if (r) { return r; }
const response = await fetch(e.request);
const cache = await caches.open(cacheName);
console.log(`[Service Worker] Caching new resource: ${e.request.url}`);
cache.put(e.request, response.clone());
return response;
})());
});
Online audit:
const appShellFiles = ['index.html',
'help.html',
'destinations.html',
'contact.html',
'js/main.js',
'css/style.css',
'sw.js'
];
Remove the sw.js from your appShellFiles

Flask_SocketIO Not emitting custom events

I have a Flask_SocketIO app that supposed to implement a chat groups system.
The client thats interacting with it is a flutter app.
I wrote a test to see if the socketio events are working. it worked once, but than stopped.
the server is getting the client's emits but not emitting back to the client.
also, the connection related evets (connect, disconnect, error) seems to be fully working. the client's callbacks on these events are called.
My flutter test client:
void main() async {
setupLocator();
final api = locator<Api>();
final socketService = locator<SocketService>();
Message msg = Message(
msgId: null,
content: "Hello!",
senderId: 1,
senderName: 'tair',
sendtime: DateTime.now().toString(),
groupId: 1);
runApp(
MaterialApp(
home: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("Disconnect"),
onPressed: () {
socketService.leave(1, 1);
}),
RaisedButton(
child: Text("Send"),
onPressed: () {
socketService.sendMessage(msg);
},
),
RaisedButton(
child: Text("Connect"),
onPressed: () {
socketService.connect(1, 1, (data) {
print('Data!');
print(data);
});
},
),
],
),
),
),
);
SharedPreferences.setMockInitialValues({});
await api.login('tair', '1234');
await socketService.getToken();
socketService.connect(1, 1, (data) {
print('Data!');
print(data);
});
Api: A class that's interacting with rest api. not related
SocketService: A class that's emitting and listening to events. im giving the connect() method
parameters in order to join a socketio room on the server side
locator: Dependency injecttion using pub package get_it. also not related
Here's the events on my Server:
#sock.on('join')
def join_group_room(data):
print(data)
token = data['token']
if token in user_token.keys():
group = Group.query.filter_by(id=int(data['groupId'])).first()
if group.temp_participants is None:
group.temp_participants = data['userId'] + ','
else:
group.temp_participants += data['userId'] + ','
db.session.commit()
join_room(data['groupId'])
#print(rooms())
else:
emit('error', 'Invalid token')
#sock.on('message')
def message_room(data):
print(data)
token = data['token']
if token in user_token.keys():
message = Message(content=data['message'], groupid=int(data['groupId']), username=user_token[token],
datetime=data['datetime'])
db.session.add(message)
db.session.commit()
participants = Group.query.filter_by(id=message.groupid).first().participants.split(",")
temp_participants = Group.query.filter_by(id=message.groupid).first().temp_participants.split(",")
for participant in participants:
if participant not in temp_participants:
pushbots.push_batch(platform=pushbots.PLATFORM_ANDROID,
alias=participant,
msg='A new message arrived', payload={'data': {'message': message.content,
'messageId': message.id,
'username': user_token[
token],
'datetime': message.datetime,
'groupId': message.groupid,
'userId': User.query.filter_by(
username=user_token[
token]).first().id}})
print("Emitting")
emit('message', {'message': message.content, 'messageId': message.id,
'username': user_token[token], 'datetime': message.datetime,
'groupId': message.groupid,
'userId': User.query.filter_by(username=user_token[token]).first().id},
room=message.groupid)
sock.sleep(0)
else:
emit('error', 'Invalid token')
#sock.on('leave')
def leave_group_room(data):
print(data)
token = data['token']
if token in user_token.keys():
group = Group.query.filter_by(id=int(data['groupId'])).first()
group.temp_participants = str(group.temp_participants.split(",").remove(data['userId'])).strip('[]')
db.session.commit()
leave_room(data['groupId'])
emit('error', 'Invalid token')
Im using eventlet as async_mode for the socketio app. i looked up online for solutions and many people said i should add the following line to the main script:
import eventlet
eventlet.monkey_patch()
Also, according to my partner on this project, the events are working fine on his machine
for further explaination, here is the link to my git repo, so you can watch the whole code: My git repo (its on integration/ClientServer branch)
Thanks for helping!
Apperantly, room names can be only strings, but the emit function wont throw an error if youll pass an int as the room parameter.

Cache in GrapghQl Flutter package settings and how to check it works

I'm trying to implement graphQl Flutter package in my app.
https://github.com/zino-app/graphql-flutter
Everything works well, but I have some issues with cache.
If we ran example from this package https://github.com/zino-app/graphql-flutter/tree/master/packages/graphql_flutter/example we can see that cache doesn't work.
In my app I also can't increase speed, it always get data online.
The code from this example
class GraphQLWidgetScreen extends StatelessWidget {
const GraphQLWidgetScreen() : super();
#override
Widget build(BuildContext context) {
final HttpLink httpLink = HttpLink(
uri: 'https://api.github.com/graphql',
);
final AuthLink authLink = AuthLink(
// ignore: undefined_identifier
getToken: () async => 'Bearer $YOUR_TOKEN',
);
Link link = authLink.concat(httpLink);
if (ENABLE_WEBSOCKETS) {
final WebSocketLink websocketLink = WebSocketLink(
url: 'ws://localhost:8080/ws/graphql',
config: SocketClientConfig(
autoReconnect: true, inactivityTimeout: Duration(seconds: 15)),
);
link = link.concat(websocketLink);
}
final ValueNotifier<GraphQLClient> client = ValueNotifier<GraphQLClient>(
GraphQLClient(
cache: OptimisticCache(
dataIdFromObject: typenameDataIdFromObject,
),
link: link,
),
);
return GraphQLProvider(
client: client,
child: const CacheProvider(
child: MyHomePage(title: 'GraphQL Widget'),
),
);
}
}
Animation that shows that cache doesn't work
So, the question is - what is the right way to implement cache and how check it works.
Thank you!
The examples are meant to be standalone - as such they use separate clients and caches. The consequence of this is that it is re-instantiated every mount. In other words, every time you navigates to the example's route, you get a new cache, so you can't see the caching effects. For a more substantial example where you can see if the cache is working, see the starwars example (related github discussion)

Websocket reconnection loop, graphql_flutter

I am using graphql_flutter package in my app. This is the code for my client:
HttpLink httpLink = HttpLink(
uri: 'https://*******/graphql',
);
WebSocketLink webSocketLink = WebSocketLink(
url: "wss://*******/graphql/websocket/",
config: SocketClientConfig(
autoReconnect: true,
inactivityTimeout: Duration(seconds: 30),
),
);
AuthLink authLink = AuthLink(
getToken: ()async{
print(await SharedPreferencesHelper.getAuthenticationToken());
return "Bearer ${await SharedPreferencesHelper.getAuthenticationToken()}";
}
);
Link link = authLink.concat(httpLink);
link = link.concat(webSocketLink);
client = ValueNotifier(
GraphQLClient(
cache: InMemoryCache(),
link: link,
),
);
However whenever I create a subscription like this:
client.value.subscribe(Operation(
document: Subscriptions.chatMessageReceived,
variables: {
"receiverId": *******
}
)).listen((fetchResult){
print(fetchResult.data);
});
I get this log in repetition:
Connecting to websocket: wss://******/graphql/websocket/... flutter:
Connected to websocket. flutter: Disconnected from websocket. flutter:
Scheduling to connect in 5 seconds... flutter: Connecting to
websocket: wss://******/graphql/websocket/...
Even though everything works fine in graphql playground. What can it be?
this is because of inactivityTimeout: Duration(seconds: 30), in WebSocketLink config
you can increase the Duration to prevent it from auto disconnecting.