I have wrote the following code on server.
server code:
import 'dart:convert';
import 'package:mongo_dart/mongo_dart.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
class PostsSocketApi {
PostsSocketApi(this.store);
final List<WebSocketChannel> _sockets = [];
final DbCollection store;
Handler get router {
return webSocketHandler((WebSocketChannel socket) {
socket.stream.listen((message) async {
final data = json.decode(message);
print(data);
if (data['action'] == 'LOGIN') {
final user = await store.findOne(
where.eq('name', data['name']).eq('password', data['password']));
if (user != null) {
for (final ws in _sockets) {
ws.sink.add(json.encode('name'));
// probably there must be .toString() ^^^
}
}
if (user == null) {
for (final ws in _sockets) {
ws.sink.addError('NOSUCHUSER');
}
}
}
});
_sockets.add(socket);
});
}
}
And now I want to get the 'name' field into my variable tmp_name to compare it with name on login field, like that:
login code:
void loginUser() async {
final name = emailController.text;
final password = passwordController.text;
widget.api.send(
json.encode({'action': 'LOGIN', 'name': name, 'password': password}));
String tmp_name = widget.api.getName;
// method from API ^^^^^^^
if (tmp_name == name) {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
prefs.setString('name', name);
});
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) => Home()));
} else {
print('error: no such user');
}
}
API code in App:
class PostsSocketApi {
PostsSocketApi()
: _api = WebSocketChannel.connect(
Uri.parse('ws://localhost:8082/posts-ws/'));
final WebSocketChannel _api;
Stream<List<Post>> get stream => _api.stream.map<List<Post>>((data) {
final decoded = json.decode(data);
return (decoded as List)
.map<Post>(
(json) => Post.fromJson(json),
)
.toList();
});
ValueChanged<String> get send => _api.sink.add;
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List).map<Post>(
(json) => Post.fromJson(json),
);
});
}
However, I got the following error in APP code and don't know how to solve it.
Error: Expected a value of type 'String', but got one of type '_MapStream<dynamic, Iterable<Post>>'
Server code works fine (compare data and print if it's wrong user)
Server response on register:
{action: ADDUSER, name: 6, password: 6, id: 6}
Server response on login as existing user:
{action: LOGIN, name: 6, password: 6}
Server response on login as NOT-existing user:
{action: LOGIN, name: fqfqfq, password: qfqfqfq}
NOSUCHUSER
ERROR - 2022-03-21 11:55:27.183011
Asynchronous error
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
PostsSocketApi.router.<fn>.<fn>
package:io/api/socket_api.dart:79
For Ruchit:
userID type is String. If I write like that, the same error thrown.
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List)
.map<String>((json) => Post.fromJson(json).userID);
});
But, if I write like that, I get the type error: error: The return type 'String' isn't a 'Post', as required by the closure's context.
Code:
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List)
.map<Post>((json) => Post.fromJson(json).userID );
});
Any ideas? (Even about refactoring other code)
I'm tried to find some explanations in documentation, but... Write if u need some more code or explanations. Or if you can give me advice about how to make login by another way - tell me.
Please help me if you can <3
Here you are returning whole post object and you are getting as String which mismatches thus it is showing error.
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List).map<Post>(
(json) => Post.fromJson(json).field, //here field is the field you want from Post object and you are getting string so this field should have type string.
//eg. Post.fromJson(json).name
);
});