Compare commits

..

10 Commits

Author SHA1 Message Date
1aa73bbd7e Add failed attempt to fix all room names 2023-12-30 15:16:42 +13:00
6ca8f646b2 Fix null being on chat messages author temporarily 2023-12-30 14:44:35 +13:00
a40dd74b96 Close chat faster on send 2023-12-30 12:49:14 +13:00
10b84d1521 Hide "Group with" from room names 2023-12-30 12:47:48 +13:00
8ca788ccdd Add button to change image of chat 2023-12-30 12:41:40 +13:00
7c1e18c4e8 Add avatar to rooms 2023-12-30 11:47:27 +13:00
76411aa827 Fix login flow and room name updates
1. Logging in with saved credentials should
just go straight to rooms page without
flickering the login page
2. Rooms should be updated if an event
fires for their names changing
2023-12-30 11:39:34 +13:00
27b7f79d74 Only login if the client is logged out 2023-12-30 11:23:57 +13:00
f229c0371b Save username/password instead of tokens
The tokens never worked. I don't know what i'm doing wrong but fluffychat basically just logs in and never tries to save anything. Im not sure how im meant to do this.
2023-12-30 11:17:21 +13:00
1cd8ba41ae Reduce nesting of login.dart 2023-12-30 11:16:38 +13:00
6 changed files with 114 additions and 42 deletions

View File

@ -24,23 +24,17 @@ class _LoginPageState extends State<LoginPage> {
loggingIn = true; loggingIn = true;
}); });
try { final provider = Provider.of<ZenithClientProvider>(context, listen: false);
final provider =
Provider.of<ZenithClientProvider>(context, listen: false);
final client = Client("zenith"); final client = Client("zenith");
try {
await client.checkHomeserver(Uri.parse(serverController.text)); await client.checkHomeserver(Uri.parse(serverController.text));
final result = await client.login( await client.login(
LoginType.mLoginPassword, LoginType.mLoginPassword,
password: passwordController.text, password: passwordController.text,
identifier: AuthenticationUserIdentifier(user: usernameController.text), identifier: AuthenticationUserIdentifier(user: usernameController.text),
refreshToken: true,
); );
provider.setClient(client);
final prefs = await SharedPreferences.getInstance();
prefs.setString("homeserver", serverController.text);
prefs.setString("username", usernameController.text);
prefs.setString("accessToken", result.accessToken);
prefs.setString("refreshToken", result.refreshToken ?? "");
} catch (error) { } catch (error) {
print(error); print(error);
setState(() { setState(() {
@ -60,6 +54,12 @@ class _LoginPageState extends State<LoginPage> {
}); });
} }
provider.setClient(client);
final prefs = await SharedPreferences.getInstance();
prefs.setString("homeserver", serverController.text);
prefs.setString("username", usernameController.text);
prefs.setString("password", passwordController.text);
if (!mounted) return; if (!mounted) return;
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
@ -81,7 +81,7 @@ class _LoginPageState extends State<LoginPage> {
title: const Text("Login"), title: const Text("Login"),
), ),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(8.0),
child: Center( child: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,

View File

@ -44,22 +44,24 @@ class _MyHomePageState extends State<MyHomePage> {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final homeserver = prefs.getString("homeserver"); final homeserver = prefs.getString("homeserver");
final username = prefs.getString("username"); final username = prefs.getString("username");
final accessToken = prefs.getString("accessToken"); final password = prefs.getString("password");
final refreshToken = prefs.getString("refreshToken");
if (homeserver == null || username == null || accessToken == null) return; if (homeserver == null || username == null || password == null) return;
if (!mounted) return; if (!mounted) return;
final provider = Provider.of<ZenithClientProvider>(context, listen: false); final provider = Provider.of<ZenithClientProvider>(context, listen: false);
final client = Client("zenith"); final client = Client("zenith");
try {
await client.checkHomeserver(Uri.parse(homeserver));
await client.login(LoginType.mLoginToken, token: accessToken);
provider.setClient(client); provider.setClient(client);
setState(() { setState(() {
showRooms = true; showRooms = true;
}); });
try {
await client.checkHomeserver(Uri.parse(homeserver));
if (!client.isLogged())
await client.login(LoginType.mLoginPassword,
password: password,
identifier: AuthenticationUserIdentifier(user: username));
} catch (error) { } catch (error) {
print(error); print(error);
setState(() { setState(() {
@ -76,6 +78,19 @@ class _MyHomePageState extends State<MyHomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (errorMessage.isNotEmpty)
return Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
errorMessage = "";
});
},
child: const Text("Clear")),
ErrorWidget(errorMessage),
],
);
if (showRooms) if (showRooms)
return const RoomsPage(); return const RoomsPage();
else else

View File

@ -1,5 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
@ -34,6 +36,16 @@ class _RoomPageState extends State<RoomPage> {
}); });
} }
void setAvatar() async {
final participants = widget.room.getParticipants();
final picked = await FilePicker.platform.pickFiles(type: FileType.image);
if (picked == null) return;
final file = File(picked.files.single.path!);
final bytes = await file.readAsBytes();
final uri = await widget.room.client.uploadContent(bytes);
await widget.room.client.setAvatarUrl(participants[0].id, uri);
}
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
@ -54,10 +66,9 @@ class _RoomPageState extends State<RoomPage> {
itemCount: messages?.length, itemCount: messages?.length,
reverse: true, reverse: true,
itemBuilder: (context, index) => ListTile( itemBuilder: (context, index) => ListTile(
title: Text(messages![index] title: Text(
.senderFromMemoryOrFallback messages![index].senderFromMemoryOrFallback.displayName ??
.displayName ""),
.toString()),
subtitle: Text(messages![index].body), subtitle: Text(messages![index].body),
leading: leading:
messages![index].senderFromMemoryOrFallback.avatarUrl != messages![index].senderFromMemoryOrFallback.avatarUrl !=
@ -74,11 +85,12 @@ class _RoomPageState extends State<RoomPage> {
), ),
TextFormField( TextFormField(
controller: chatController, controller: chatController,
textCapitalization: TextCapitalization.sentences,
textInputAction: TextInputAction.send,
decoration: const InputDecoration(hintText: 'Message'), decoration: const InputDecoration(hintText: 'Message'),
onFieldSubmitted: (value) async { onFieldSubmitted: (value) async {
print("Sending text event $value to room ${widget.room.id}...");
await widget.room.sendTextEvent(value);
chatController.text = ''; chatController.text = '';
await widget.room.sendTextEvent(value);
}, },
), ),
]; ];
@ -89,18 +101,18 @@ class _RoomPageState extends State<RoomPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary, backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.room.getLocalizedDisplayname()), title: Text(widget.room
.getLocalizedDisplayname()
.replaceFirst(RegExp("Group with "), "")),
actions: [
IconButton(onPressed: setAvatar, icon: const Icon(Icons.image))
],
), ),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(8.0),
child: Column( child: Column(
children: getChildren(), children: getChildren(),
)), )),
floatingActionButton: FloatingActionButton(
onPressed: sendMessage,
tooltip: 'Send message',
child: const Icon(Icons.send),
),
); );
} }
} }

View File

@ -28,6 +28,22 @@ class _RoomsPageState extends State<RoomsPage> {
context, MaterialPageRoute(builder: (context) => RoomPage(room: room))); context, MaterialPageRoute(builder: (context) => RoomPage(room: room)));
} }
void fixNames(Client client) async {
final rooms = client.rooms
.where((element) =>
element.getLocalizedDisplayname().contains("Group with"))
.toList();
for (final room in rooms) {
print("Setting power level to 100...");
final result = await room.setPower(client.userID!, 100);
print("Result=$result");
print("Fixing ${room.getLocalizedDisplayname()}...");
await room.setName(
room.getLocalizedDisplayname().replaceAll(RegExp("Group with"), ""));
}
print("Fixed all.");
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -78,33 +94,45 @@ class _RoomsPageState extends State<RoomsPage> {
], ],
), ),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(8.0),
child: Center(child: Consumer<ZenithClientProvider>( child: Center(child: Consumer<ZenithClientProvider>(
builder: (context, provider, child) { builder: (context, provider, child) {
provider.client.roomsLoading?.then((value) { print(provider.client.rooms
.where((element) =>
element.getLocalizedDisplayname().contains("Group with"))
.length);
provider.client.onRoomState.stream.listen((event) {
setState(() { setState(() {
loadingRooms = false; loadingRooms = false;
}); });
}); });
if (provider.client.roomsLoading != null && loadingRooms) return ElevatedButton(
onPressed: () => fixNames(provider.client),
child: const Text("Fix names"));
if (provider.client.rooms.isEmpty)
return const CircularProgressIndicator(); return const CircularProgressIndicator();
else else
return ListView.builder( return ListView.builder(
itemCount: provider.client.rooms.length, itemCount: provider.client.rooms.length,
itemBuilder: (context, index) => ListTile( itemBuilder: (context, index) => ListTile(
title: Text(provider.client.rooms[index] title: Text(provider.client.rooms[index]
.getLocalizedDisplayname()), .getLocalizedDisplayname()
.replaceFirst(RegExp("Group with "), "")),
leading: CircleAvatar(
foregroundImage: NetworkImage(provider
.client.rooms[index].avatar
?.getThumbnail(provider.client,
width: 50, height: 50)
.toString() ??
"")),
onTap: () => viewRoom(provider.client.rooms[index]), onTap: () => viewRoom(provider.client.rooms[index]),
)); ));
}, },
)), )),
), ),
floatingActionButton: FloatingActionButton(
onPressed: sendMessage,
tooltip: 'Send message',
child: const Icon(Icons.send),
),
); );
} }
} }

View File

@ -145,6 +145,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.0" version: "7.0.0"
file_picker:
dependency: "direct main"
description:
name: file_picker
sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6"
url: "https://pub.dev"
source: hosted
version: "6.1.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -174,6 +182,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.0" version: "0.3.0"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
url: "https://pub.dev"
source: hosted
version: "2.0.17"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter

View File

@ -40,6 +40,7 @@ dependencies:
flutter_openssl_crypto: ^0.3.0 flutter_openssl_crypto: ^0.3.0
provider: ^6.1.1 provider: ^6.1.1
shared_preferences: ^2.2.2 shared_preferences: ^2.2.2
file_picker: ^6.1.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: