2022-11-08 16:54:19 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:logging/logging.dart';
|
|
|
|
import 'package:moxdns/moxdns.dart';
|
|
|
|
import 'package:moxxmpp/moxxmpp.dart';
|
2022-11-08 19:05:22 +00:00
|
|
|
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
|
2022-11-08 16:54:19 +00:00
|
|
|
|
|
|
|
class ExampleTcpSocketWrapper extends TCPSocketWrapper {
|
2023-03-30 14:18:28 +00:00
|
|
|
ExampleTcpSocketWrapper() : super();
|
2022-11-08 16:54:19 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Future<List<MoxSrvRecord>> srvQuery(String domain, bool dnssec) async {
|
|
|
|
final records = await MoxdnsPlugin.srvQuery(domain, false);
|
|
|
|
return records
|
2023-03-08 20:07:55 +00:00
|
|
|
.map(
|
|
|
|
(record) => MoxSrvRecord(
|
|
|
|
record.priority,
|
|
|
|
record.weight,
|
|
|
|
record.target,
|
|
|
|
record.port,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.toList();
|
2022-11-08 16:54:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
Logger.root.level = Level.ALL;
|
|
|
|
Logger.root.onRecord.listen((record) {
|
2023-03-08 20:07:55 +00:00
|
|
|
// ignore: avoid_print
|
2022-11-08 16:54:19 +00:00
|
|
|
print('${record.level.name}: ${record.time}: ${record.message}');
|
|
|
|
});
|
|
|
|
|
|
|
|
runApp(const MyApp());
|
|
|
|
}
|
|
|
|
|
|
|
|
class MyApp extends StatelessWidget {
|
|
|
|
const MyApp({super.key});
|
|
|
|
|
|
|
|
// This widget is the root of your application.
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return MaterialApp(
|
|
|
|
title: 'Moxxmpp Demo',
|
|
|
|
theme: ThemeData(primarySwatch: Colors.blue),
|
|
|
|
home: const MyHomePage(title: 'Moxxmpp Demo Home Page'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class MyHomePage extends StatefulWidget {
|
|
|
|
const MyHomePage({super.key, required this.title});
|
|
|
|
|
|
|
|
final String title;
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<MyHomePage> createState() => _MyHomePageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
2023-03-08 20:07:55 +00:00
|
|
|
final logger = Logger('MyHomePage');
|
2022-11-08 16:54:19 +00:00
|
|
|
final XmppConnection connection = XmppConnection(
|
2023-03-08 18:02:43 +00:00
|
|
|
RandomBackoffReconnectionPolicy(1, 60),
|
|
|
|
AlwaysConnectedConnectivityManager(),
|
2023-04-03 14:05:20 +00:00
|
|
|
ClientToServerNegotiator(),
|
2023-03-10 18:29:30 +00:00
|
|
|
// The below causes the app to crash.
|
|
|
|
//ExampleTcpSocketWrapper(),
|
|
|
|
// In a production app, the below should be false.
|
2023-03-30 14:18:28 +00:00
|
|
|
TCPSocketWrapper(),
|
2022-11-08 16:54:19 +00:00
|
|
|
);
|
|
|
|
TextEditingController jidController = TextEditingController();
|
|
|
|
TextEditingController passwordController = TextEditingController();
|
2023-03-08 18:02:43 +00:00
|
|
|
bool connected = false;
|
|
|
|
bool loading = false;
|
2022-11-08 16:54:19 +00:00
|
|
|
|
|
|
|
_MyHomePageState() : super() {
|
|
|
|
connection
|
|
|
|
..registerManagers([
|
|
|
|
StreamManagementManager(),
|
2023-03-08 18:02:43 +00:00
|
|
|
DiscoManager([]),
|
|
|
|
RosterManager(TestingRosterStateManager("", [])),
|
2023-03-29 13:25:17 +00:00
|
|
|
PingManager(
|
|
|
|
const Duration(minutes: 3),
|
|
|
|
),
|
2022-11-08 16:54:19 +00:00
|
|
|
MessageManager(),
|
2023-03-08 18:02:43 +00:00
|
|
|
PresenceManager(),
|
2022-11-08 16:54:19 +00:00
|
|
|
])
|
|
|
|
..registerFeatureNegotiators([
|
|
|
|
ResourceBindingNegotiator(),
|
|
|
|
StartTlsNegotiator(),
|
|
|
|
StreamManagementNegotiator(),
|
|
|
|
CSINegotiator(),
|
|
|
|
RosterFeatureNegotiator(),
|
|
|
|
SaslPlainNegotiator(),
|
2022-11-16 14:37:20 +00:00
|
|
|
SaslScramNegotiator(10, '', '', ScramHashType.sha512),
|
2022-11-08 16:54:19 +00:00
|
|
|
SaslScramNegotiator(9, '', '', ScramHashType.sha256),
|
|
|
|
SaslScramNegotiator(8, '', '', ScramHashType.sha1),
|
|
|
|
]);
|
|
|
|
}
|
2023-03-08 19:09:37 +00:00
|
|
|
|
2022-11-08 16:54:19 +00:00
|
|
|
Future<void> _buttonPressed() async {
|
2023-03-08 18:02:43 +00:00
|
|
|
if (connected) {
|
|
|
|
await connection.disconnect();
|
2023-03-08 20:07:55 +00:00
|
|
|
setState(() {
|
|
|
|
connected = false;
|
|
|
|
});
|
2023-03-08 18:02:43 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-03-08 20:07:55 +00:00
|
|
|
setState(() {
|
|
|
|
loading = true;
|
|
|
|
});
|
2022-11-08 16:54:19 +00:00
|
|
|
connection.setConnectionSettings(
|
|
|
|
ConnectionSettings(
|
|
|
|
jid: JID.fromString(jidController.text),
|
|
|
|
password: passwordController.text,
|
|
|
|
useDirectTLS: true,
|
|
|
|
),
|
|
|
|
);
|
2023-03-11 17:54:36 +00:00
|
|
|
final result = await connection.connect(waitUntilLogin: true);
|
2023-03-08 20:07:55 +00:00
|
|
|
setState(() {
|
2023-03-11 17:54:36 +00:00
|
|
|
connected = result.isType<bool>() && result.get<bool>();
|
2023-03-08 20:07:55 +00:00
|
|
|
loading = false;
|
|
|
|
});
|
2023-03-18 13:59:47 +00:00
|
|
|
if (result.isType<XmppError>()) {
|
|
|
|
logger.severe(result.get<XmppError>());
|
2023-03-08 19:09:37 +00:00
|
|
|
if (context.mounted) {
|
2023-03-08 20:07:55 +00:00
|
|
|
showDialog(
|
2023-03-10 18:29:30 +00:00
|
|
|
context: context,
|
|
|
|
builder: (_) => AlertDialog(
|
|
|
|
title: const Text('Error'),
|
2023-03-18 13:59:47 +00:00
|
|
|
content: Text(result.get<XmppError>().toString()),
|
2023-03-10 18:29:30 +00:00
|
|
|
),
|
|
|
|
);
|
2023-03-08 19:09:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-08 16:54:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
|
|
|
appBar: AppBar(
|
|
|
|
title: Text(widget.title),
|
2023-03-08 18:02:43 +00:00
|
|
|
backgroundColor: connected ? Colors.green : Colors.deepPurple[800],
|
|
|
|
foregroundColor: connected ? Colors.black : Colors.white,
|
2022-11-08 16:54:19 +00:00
|
|
|
),
|
|
|
|
body: Center(
|
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
|
|
|
TextField(
|
2023-03-08 18:02:43 +00:00
|
|
|
enabled: !loading,
|
2022-11-08 16:54:19 +00:00
|
|
|
controller: jidController,
|
2023-03-08 20:07:55 +00:00
|
|
|
decoration: const InputDecoration(
|
2022-11-08 16:54:19 +00:00
|
|
|
labelText: 'JID',
|
|
|
|
),
|
|
|
|
),
|
|
|
|
TextField(
|
2023-03-08 18:02:43 +00:00
|
|
|
enabled: !loading,
|
2022-11-08 16:54:19 +00:00
|
|
|
controller: passwordController,
|
2023-03-08 20:07:55 +00:00
|
|
|
decoration: const InputDecoration(
|
2022-11-08 16:54:19 +00:00
|
|
|
labelText: 'Password',
|
|
|
|
),
|
|
|
|
obscureText: true,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
2023-03-08 18:02:43 +00:00
|
|
|
floatingActionButton: FloatingActionButton.extended(
|
2022-11-08 16:54:19 +00:00
|
|
|
onPressed: _buttonPressed,
|
2023-03-08 18:02:43 +00:00
|
|
|
label: Text(connected ? 'Disconnect' : 'Connect'),
|
|
|
|
backgroundColor: Colors.blue,
|
|
|
|
foregroundColor: Colors.white,
|
2022-11-08 16:54:19 +00:00
|
|
|
tooltip: 'Connect',
|
2023-03-08 18:02:43 +00:00
|
|
|
icon: const Icon(Icons.power),
|
2022-11-08 16:54:19 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|