Compare commits

..
14 Commits
Author SHA1 Message Date
brandon.presley 11de9ccfe8 Turn off autocorrect/capitalization for login 2023-12-30 16:17:05 +13:00
brandon.presley 128a1bf35f Add persistence to matrix Client 2023-12-30 16:11:20 +13:00
brandon.presley a552c30ba0 Remove logging of rooms with "Group with" 2023-12-30 16:00:54 +13:00
brandon.presley 2039b4e90d Remove custom code for renaming groups
Was something for my local matrix
environment, committed
accidentally.
2023-12-30 15:54:30 +13:00
brandon.presley 1aa73bbd7e Add failed attempt to fix all room names 2023-12-30 15:16:42 +13:00
brandon.presley 6ca8f646b2 Fix null being on chat messages author temporarily 2023-12-30 14:44:35 +13:00
brandon.presley a40dd74b96 Close chat faster on send 2023-12-30 12:49:14 +13:00
brandon.presley 10b84d1521 Hide "Group with" from room names 2023-12-30 12:47:48 +13:00
brandon.presley 8ca788ccdd Add button to change image of chat 2023-12-30 12:41:40 +13:00
brandon.presley 7c1e18c4e8 Add avatar to rooms 2023-12-30 11:47:27 +13:00
brandon.presley 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
brandon.presley 27b7f79d74 Only login if the client is logged out 2023-12-30 11:23:57 +13:00
brandon.presley 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
brandon.presley 1cd8ba41ae Reduce nesting of login.dart 2023-12-30 11:16:38 +13:00
8 changed files with 128 additions and 54 deletions
+15 -13
View File
@@ -24,23 +24,16 @@ class _LoginPageState extends State<LoginPage> {
loggingIn = true;
});
final provider = Provider.of<ZenithClientProvider>(context, listen: false);
try {
final provider =
Provider.of<ZenithClientProvider>(context, listen: false);
final client = Client("zenith");
await client.checkHomeserver(Uri.parse(serverController.text));
final result = await client.login(
await provider.client.checkHomeserver(Uri.parse(serverController.text));
await provider.client.login(
LoginType.mLoginPassword,
password: passwordController.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) {
print(error);
setState(() {
@@ -60,6 +53,11 @@ class _LoginPageState extends State<LoginPage> {
});
}
final prefs = await SharedPreferences.getInstance();
prefs.setString("homeserver", serverController.text);
prefs.setString("username", usernameController.text);
prefs.setString("password", passwordController.text);
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
@@ -81,23 +79,27 @@ class _LoginPageState extends State<LoginPage> {
title: const Text("Login"),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: serverController,
autocorrect: false,
textCapitalization: TextCapitalization.none,
decoration: const InputDecoration(
labelText: 'Server', hintText: 'https://matrix.org'),
),
TextFormField(
controller: usernameController,
autocorrect: false,
decoration: const InputDecoration(
labelText: 'Username', hintText: 'john'),
),
TextFormField(
controller: passwordController,
autocorrect: false,
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
onFieldSubmitted: (value) => login(),
+22 -9
View File
@@ -44,22 +44,22 @@ class _MyHomePageState extends State<MyHomePage> {
final prefs = await SharedPreferences.getInstance();
final homeserver = prefs.getString("homeserver");
final username = prefs.getString("username");
final accessToken = prefs.getString("accessToken");
final refreshToken = prefs.getString("refreshToken");
final password = prefs.getString("password");
if (homeserver == null || username == null || accessToken == null) return;
if (homeserver == null || username == null || password == null) return;
if (!mounted) return;
final provider = Provider.of<ZenithClientProvider>(context, listen: false);
final client = Client("zenith");
try {
await client.checkHomeserver(Uri.parse(homeserver));
await client.login(LoginType.mLoginToken, token: accessToken);
provider.setClient(client);
setState(() {
showRooms = true;
});
try {
await provider.client.checkHomeserver(Uri.parse(homeserver));
if (!provider.client.isLogged())
await provider.client.login(LoginType.mLoginPassword,
password: password,
identifier: AuthenticationUserIdentifier(user: username));
} catch (error) {
print(error);
setState(() {
@@ -76,6 +76,19 @@ class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
if (errorMessage.isNotEmpty)
return Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
errorMessage = "";
});
},
child: const Text("Clear")),
ErrorWidget(errorMessage),
],
);
if (showRooms)
return const RoomsPage();
else
+25 -13
View File
@@ -1,5 +1,7 @@
import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.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
void dispose() {
super.dispose();
@@ -54,10 +66,9 @@ class _RoomPageState extends State<RoomPage> {
itemCount: messages?.length,
reverse: true,
itemBuilder: (context, index) => ListTile(
title: Text(messages![index]
.senderFromMemoryOrFallback
.displayName
.toString()),
title: Text(
messages![index].senderFromMemoryOrFallback.displayName ??
""),
subtitle: Text(messages![index].body),
leading:
messages![index].senderFromMemoryOrFallback.avatarUrl !=
@@ -74,11 +85,12 @@ class _RoomPageState extends State<RoomPage> {
),
TextFormField(
controller: chatController,
textCapitalization: TextCapitalization.sentences,
textInputAction: TextInputAction.send,
decoration: const InputDecoration(hintText: 'Message'),
onFieldSubmitted: (value) async {
print("Sending text event $value to room ${widget.room.id}...");
await widget.room.sendTextEvent(value);
chatController.text = '';
await widget.room.sendTextEvent(value);
},
),
];
@@ -89,18 +101,18 @@ class _RoomPageState extends State<RoomPage> {
return Scaffold(
appBar: AppBar(
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(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(8.0),
child: Column(
children: getChildren(),
)),
floatingActionButton: FloatingActionButton(
onPressed: sendMessage,
tooltip: 'Send message',
child: const Icon(Icons.send),
),
);
}
}
+12 -9
View File
@@ -78,33 +78,36 @@ class _RoomsPageState extends State<RoomsPage> {
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(8.0),
child: Center(child: Consumer<ZenithClientProvider>(
builder: (context, provider, child) {
provider.client.roomsLoading?.then((value) {
provider.client.onRoomState.stream.listen((event) {
setState(() {
loadingRooms = false;
});
});
if (provider.client.roomsLoading != null && loadingRooms)
if (provider.client.rooms.isEmpty)
return const CircularProgressIndicator();
else
return ListView.builder(
itemCount: provider.client.rooms.length,
itemBuilder: (context, index) => ListTile(
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]),
));
},
)),
),
floatingActionButton: FloatingActionButton(
onPressed: sendMessage,
tooltip: 'Send message',
child: const Icon(Icons.send),
),
);
}
}
+8 -8
View File
@@ -1,13 +1,13 @@
import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:path_provider/path_provider.dart';
class ZenithClientProvider extends ChangeNotifier {
late Client _client;
Client get client => _client;
void setClient(Client value) {
_client = value;
notifyListeners();
}
final client = Client("zenith", databaseBuilder: (_) async {
final dir =
await getApplicationSupportDirectory(); // Recommend path_provider package
final db = HiveCollectionsDatabase('matrix_example_chat', dir.path);
await db.open();
return db;
});
}
@@ -5,8 +5,10 @@
import FlutterMacOS
import Foundation
import path_provider_foundation
import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
}
+41 -1
View File
@@ -145,6 +145,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: "direct main"
description: flutter
@@ -174,6 +182,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: "direct dev"
description: flutter
@@ -328,6 +344,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.3"
path_provider:
dependency: "direct main"
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_linux:
dependency: transitive
description:
@@ -607,4 +647,4 @@ packages:
version: "6.3.0"
sdks:
dart: ">=3.1.5 <4.0.0"
flutter: ">=3.7.0"
flutter: ">=3.10.0"
+2
View File
@@ -40,6 +40,8 @@ dependencies:
flutter_openssl_crypto: ^0.3.0
provider: ^6.1.1
shared_preferences: ^2.2.2
file_picker: ^6.1.1
path_provider: ^2.1.1
dev_dependencies:
flutter_test: