I've been frustrated with this error with the getstream api for a while now, especially because it is erratic. I don't know exactly how to reproduce it, which makes it tough to debug. My only "solution" to it is to log out and log back in (this forces the user to reconnect to the get stream api server), thereby, getting the token again. But obviously, this shouldn't have to be the case.
I get this error whenever I open a message between two people.
Here's the main.dart where I initialize the stream client
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final client = StreamChatClient(
STREAM_API_KEY,
logLevel: Level.OFF,
);
runApp(MyApp(
client: client,
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key, required this.client}) : super(key: key);
final StreamChatClient client;
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Provider<BaseAuth>(
create: (context) => Auth(), //provide an instance of our Auth Service to the entire app
child: MaterialApp(
title: 'App',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: const SplashscreenWidget(),
debugShowCheckedModeBanner: false,
builder: (context, widget) => StreamChat( //was StreamChatCore
client: client,
child: widget!,
),
),
);
}
Here in my main page, I connect the user to the get stream api. I have left out the parts of the code that are not pertinent to this question. It is impossible for a user to get to messages without first getting to this home page. So it should not be possible for the user to have an unauthorized token when they open a message:
void initState() {
super.initState();
//only connect user if coming from signup or login page
if(widget.fromSignUpOrLogin) {
connectUser = _connectUser();
}
}
_connectUser() async {
final client = StreamChatCore.of(context).client;
FireStoreDatabase db = FireStoreDatabase(uid: FirebaseAuth.instance.currentUser!.uid);
AppUser appUser = await db.readUser();
final user = su.User(id: uid,
extraData: {
"name": appUser.username,
"image": appUser.photoUrl,
}
);
await client.connectUser(
user,
appUser.streamToken
);
}
Lastly, here's my page of a message between two people. Again, I have left out the code that's not the scope of this question:
late Channel globalChannel;
initMessageSystem() async {
globalChannel = widget.client.channel('messaging', id: widget.channelId);
await globalChannel.watch();
}
@override
void initState() {
super.initState();
initMessageSystem();
}
@override
Widget build(BuildContext context) {
return StreamChat( ///this must be here as the root of the message chat
client: widget.client,
child: StreamChannel
(
child: _buildBody(),
channel: globalChannel,
),
streamChatThemeData: StreamChatThemeData(
colorTheme: StreamColorTheme.light(
accentPrimary: Colors.purpleAccent,
textHighEmphasis: Colors.purpleAccent,
),
ownMessageTheme: const StreamMessageThemeData(
messageBackgroundColor: Colors.purpleAccent,
messageTextStyle: TextStyle(
color: Colors.white
)
)
)
);
}
Because of how erratic the problem is, I believe a possible solution is to check whether or not a client is connected first in the initMessage() function and then connect the client if they are not and do nothing if they are. However, the get stream api is not to clear on how to check if a client is connected using dart. So I was wondering how to check for this? or better still, if there is a better solution for what I am experiencing.