forked from Henry-Hiles/nexus
wip mentions
This commit is contained in:
parent
819512c737
commit
541933a939
11 changed files with 145 additions and 86 deletions
|
|
@ -10,6 +10,11 @@ import "package:nexus/controllers/secure_storage_controller.dart";
|
||||||
import "package:nexus/models/session_backup.dart";
|
import "package:nexus/models/session_backup.dart";
|
||||||
|
|
||||||
class ClientController extends AsyncNotifier<Client> {
|
class ClientController extends AsyncNotifier<Client> {
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(
|
||||||
|
AsyncValue<Client> previous,
|
||||||
|
AsyncValue<Client> next,
|
||||||
|
) => previous.hasValue != next.hasValue;
|
||||||
static const sessionBackupKey = "sessionBackup";
|
static const sessionBackupKey = "sessionBackup";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -81,7 +86,7 @@ class ClientController extends AsyncNotifier<Client> {
|
||||||
).toJson(),
|
).toJson(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
ref.invalidateSelf();
|
ref.invalidateSelf(asReload: true);
|
||||||
return true;
|
return true;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -92,11 +92,18 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
Future<void> updateMessage(Message message, Message newMessage) async =>
|
Future<void> updateMessage(Message message, Message newMessage) async =>
|
||||||
(await future).updateMessage(message, newMessage);
|
(await future).updateMessage(message, newMessage);
|
||||||
|
|
||||||
Future<void> send(String message, {Message? replyTo}) async =>
|
Future<void> send(Message message, {Message? replyTo}) async {
|
||||||
|
final controller = await future;
|
||||||
|
controller.insertMessage(message);
|
||||||
|
|
||||||
|
if (message is TextMessage) {
|
||||||
await room.sendTextEvent(
|
await room.sendTextEvent(
|
||||||
message,
|
message.text,
|
||||||
inReplyTo: replyTo == null ? null : await room.getEventById(replyTo.id),
|
inReplyTo: replyTo == null ? null : await room.getEventById(replyTo.id),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
// TODO: Handle other types of message
|
||||||
|
}
|
||||||
|
|
||||||
Future<chat.User> resolveUser(String id) async {
|
Future<chat.User> resolveUser(String id) async {
|
||||||
final user = await room.client.getUserProfile(id);
|
final user = await room.client.getUserProfile(id);
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ extension EventToMessage on Event {
|
||||||
id: eventId,
|
id: eventId,
|
||||||
authorId: senderId,
|
authorId: senderId,
|
||||||
text:
|
text:
|
||||||
"${content["displayname"]} ${switch (Membership.values.firstWhereOrNull((membership) => membership.name == content["membership"])) {
|
"${sender.displayName} ${switch (Membership.values.firstWhereOrNull((membership) => membership.name == content["membership"])) {
|
||||||
Membership.invite => "was invited to",
|
Membership.invite => "was invited to",
|
||||||
Membership.join => "joined",
|
Membership.join => "joined",
|
||||||
Membership.leave => "left",
|
Membership.leave => "left",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "package:flutter/foundation.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/client_controller.dart";
|
import "package:nexus/controllers/client_controller.dart";
|
||||||
import "package:nexus/controllers/shared_prefs_controller.dart";
|
import "package:nexus/controllers/shared_prefs_controller.dart";
|
||||||
|
|
@ -13,7 +14,23 @@ import "package:window_size/window_size.dart";
|
||||||
|
|
||||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
final class Logger extends ProviderObserver {
|
||||||
|
@override
|
||||||
|
void didUpdateProvider(
|
||||||
|
ProviderObserverContext context,
|
||||||
|
Object? previousValue,
|
||||||
|
Object? newValue,
|
||||||
|
) {
|
||||||
|
print('''{
|
||||||
|
"provider": "${context.provider}",
|
||||||
|
"changed": ${previousValue != newValue}
|
||||||
|
"type": ${previousValue.runtimeType}
|
||||||
|
}''');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void showError(Object error, [StackTrace? stackTrace]) {
|
void showError(Object error, [StackTrace? stackTrace]) {
|
||||||
|
if (error.toString().contains("ParentDataWidget")) return;
|
||||||
if (error.toString().contains("DioException")) return;
|
if (error.toString().contains("DioException")) return;
|
||||||
if (error.toString().contains("UTF-16")) return;
|
if (error.toString().contains("UTF-16")) return;
|
||||||
|
|
||||||
|
|
@ -43,7 +60,9 @@ void main() async {
|
||||||
|
|
||||||
setWindowMinSize(const Size.square(500));
|
setWindowMinSize(const Size.square(500));
|
||||||
|
|
||||||
runApp(ProviderScope(child: const App()));
|
runApp(
|
||||||
|
ProviderScope(observers: [if (kDebugMode) Logger()], child: const App()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class App extends ConsumerWidget {
|
class App extends ConsumerWidget {
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,4 @@ abstract class FullRoom with _$FullRoom {
|
||||||
required String title,
|
required String title,
|
||||||
required Uri? avatar,
|
required Uri? avatar,
|
||||||
}) = _FullRoom;
|
}) = _FullRoom;
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
other.runtimeType == runtimeType &&
|
|
||||||
other is FullRoom &&
|
|
||||||
other.avatar == avatar &&
|
|
||||||
other.title == title;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType, title, avatar);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,4 @@ abstract class Space with _$Space {
|
||||||
Uri? avatar,
|
Uri? avatar,
|
||||||
Icon? icon,
|
Icon? icon,
|
||||||
}) = _Space;
|
}) = _Space;
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
other.runtimeType == runtimeType &&
|
|
||||||
other is Space &&
|
|
||||||
other.title == title &&
|
|
||||||
other.id == id &&
|
|
||||||
other.icon == icon &&
|
|
||||||
other.avatar == avatar;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType, title, id, icon, avatar);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,64 +1,101 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:flutter_chat_ui/flutter_chat_ui.dart";
|
import "package:flutter_chat_ui/flutter_chat_ui.dart";
|
||||||
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
|
import "package:fluttertagger/fluttertagger.dart";
|
||||||
|
import "package:matrix/matrix.dart";
|
||||||
|
import "package:nexus/helpers/extensions/get_headers.dart";
|
||||||
|
import "package:nexus/widgets/form_text_input.dart";
|
||||||
|
|
||||||
class ChatBox extends StatelessWidget {
|
class ChatBox extends HookWidget {
|
||||||
final Message? replyToMessage;
|
final Message? replyToMessage;
|
||||||
final VoidCallback onDismiss;
|
final VoidCallback onDismiss;
|
||||||
final Map<String, String> headers;
|
final Room room;
|
||||||
const ChatBox({
|
const ChatBox({
|
||||||
required this.replyToMessage,
|
required this.replyToMessage,
|
||||||
required this.onDismiss,
|
required this.onDismiss,
|
||||||
required this.headers,
|
required this.room,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Composer(
|
Widget build(BuildContext context) {
|
||||||
sigmaX: 0,
|
final theme = Theme.of(context);
|
||||||
sigmaY: 0,
|
final controller = useRef(FlutterTaggerController());
|
||||||
sendIconColor: Theme.of(context).colorScheme.primary,
|
final trigger = useState<String?>(null);
|
||||||
sendOnEnter: true,
|
final style = TextStyle(
|
||||||
topWidget: replyToMessage == null
|
color: theme.colorScheme.primary,
|
||||||
? null
|
fontWeight: FontWeight.bold,
|
||||||
: ColoredBox(
|
);
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
|
||||||
child: Padding(
|
return Column(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
child: Row(
|
children: [
|
||||||
spacing: 8,
|
FlutterTagger(
|
||||||
children: [
|
overlay: SizedBox(),
|
||||||
Avatar(
|
controller: controller.value,
|
||||||
userId: replyToMessage!.authorId,
|
onSearch: (query, triggerCharacter) {
|
||||||
headers: headers,
|
triggerCharacter == "#";
|
||||||
size: 16,
|
if (controller.value.tags.isEmpty)
|
||||||
),
|
controller.value.addTag(id: "id", name: "name");
|
||||||
Text(
|
},
|
||||||
replyToMessage!.metadata?["displayName"] ??
|
triggerCharacterAndStyles: {"@": style, "#": style},
|
||||||
replyToMessage!.authorId,
|
builder: (context, key) => TextFormField(controller: controller.value, key: key,autofocus: true,onFieldSubmitted: (_) {
|
||||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
},)
|
||||||
),
|
// Composer(
|
||||||
),
|
// textEditingController: controller.value,
|
||||||
Expanded(
|
// key: key,
|
||||||
child: (replyToMessage is TextMessage)
|
// sigmaY: 0,
|
||||||
? Text(
|
// sendIconColor: theme.colorScheme.primary,
|
||||||
(replyToMessage as TextMessage).text,
|
// sendOnEnter: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
// topWidget: replyToMessage == null
|
||||||
style: Theme.of(context).textTheme.labelMedium,
|
// ? null
|
||||||
maxLines: 1,
|
// : ColoredBox(
|
||||||
)
|
// color: theme.colorScheme.surfaceContainer,
|
||||||
: SizedBox(),
|
// child: Padding(
|
||||||
),
|
// padding: EdgeInsets.symmetric(
|
||||||
IconButton(
|
// horizontal: 16,
|
||||||
onPressed: onDismiss,
|
// vertical: 4,
|
||||||
icon: Icon(Icons.close),
|
// ),
|
||||||
iconSize: 20,
|
// child: Row(
|
||||||
),
|
// spacing: 8,
|
||||||
],
|
// children: [
|
||||||
),
|
// Avatar(
|
||||||
),
|
// userId: replyToMessage!.authorId,
|
||||||
),
|
// headers: room.client.headers,
|
||||||
autofocus: true,
|
// size: 16,
|
||||||
);
|
// ),
|
||||||
|
// Text(
|
||||||
|
// replyToMessage!.metadata?["displayName"] ??
|
||||||
|
// replyToMessage!.authorId,
|
||||||
|
// style: theme.textTheme.labelMedium?.copyWith(
|
||||||
|
// fontWeight: FontWeight.bold,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// child: (replyToMessage is TextMessage)
|
||||||
|
// ? Text(
|
||||||
|
// (replyToMessage as TextMessage).text,
|
||||||
|
// overflow: TextOverflow.ellipsis,
|
||||||
|
// style: theme.textTheme.labelMedium,
|
||||||
|
// maxLines: 1,
|
||||||
|
// )
|
||||||
|
// : SizedBox(),
|
||||||
|
// ),
|
||||||
|
// IconButton(
|
||||||
|
// onPressed: onDismiss,
|
||||||
|
// icon: Icon(Icons.close),
|
||||||
|
// iconSize: 20,
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// autofocus: true,
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,9 @@ class Html extends ConsumerWidget {
|
||||||
headers: client.headers,
|
headers: client.headers,
|
||||||
errorBuilder: (_, error, _) => Text(
|
errorBuilder: (_, error, _) => Text(
|
||||||
"Image Failed to Load",
|
"Image Failed to Load",
|
||||||
style: TextStyle(color: Colors.red),
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
height: height.toDouble(),
|
height: height.toDouble(),
|
||||||
width: width?.toDouble(),
|
width: width?.toDouble(),
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ class RoomChat extends HookConsumerWidget {
|
||||||
composerBuilder: (_) => ChatBox(
|
composerBuilder: (_) => ChatBox(
|
||||||
replyToMessage: replyToMessage.value,
|
replyToMessage: replyToMessage.value,
|
||||||
onDismiss: () => replyToMessage.value = null,
|
onDismiss: () => replyToMessage.value = null,
|
||||||
headers: room.roomData.client.headers,
|
room: room.roomData,
|
||||||
),
|
),
|
||||||
textMessageBuilder:
|
textMessageBuilder:
|
||||||
(
|
(
|
||||||
|
|
@ -296,13 +296,6 @@ class RoomChat extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onMessageSend: (message) {
|
|
||||||
notifier.send(
|
|
||||||
message,
|
|
||||||
replyTo: replyToMessage.value,
|
|
||||||
);
|
|
||||||
replyToMessage.value = null;
|
|
||||||
},
|
|
||||||
resolveUser: notifier.resolveUser,
|
resolveUser: notifier.resolveUser,
|
||||||
chatController: controller,
|
chatController: controller,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
16
pubspec.lock
16
pubspec.lock
|
|
@ -575,6 +575,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.17.0"
|
version: "0.17.0"
|
||||||
|
fluttertagger:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: fluttertagger
|
||||||
|
sha256: "3df0132bdd431a7279da78ea70500ea1e767fa093f43f32785b757c10c6a0fcc"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.1"
|
||||||
flyer_chat_file_message:
|
flyer_chat_file_message:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -912,6 +920,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.2"
|
||||||
|
mention_tag_text_field:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: mention_tag_text_field
|
||||||
|
sha256: ba7b9d8003e0f340a65c6dcdb7770f4340f653ae1612a9e31e11d12f7f1dd80f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.9"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ dependencies:
|
||||||
vodozemac: ^0.4.0
|
vodozemac: ^0.4.0
|
||||||
clipboard: ^2.0.2
|
clipboard: ^2.0.2
|
||||||
shared_preferences: ^2.5.3
|
shared_preferences: ^2.5.3
|
||||||
|
mention_tag_text_field: ^0.0.9
|
||||||
|
fluttertagger: ^2.3.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.11
|
build_runner: ^2.4.11
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue