forked from Henry-Hiles/nexus
wip
This commit is contained in:
parent
aa6b0f692c
commit
5d4ca4ffe2
2 changed files with 227 additions and 104 deletions
|
|
@ -6,6 +6,8 @@ import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
import "package:nexus/helpers/extensions/scheme_to_theme.dart";
|
import "package:nexus/helpers/extensions/scheme_to_theme.dart";
|
||||||
import "package:nexus/pages/chat_page.dart";
|
import "package:nexus/pages/chat_page.dart";
|
||||||
import "package:nexus/pages/login_page.dart";
|
import "package:nexus/pages/login_page.dart";
|
||||||
|
import "package:nexus/pages/settings_page.dart";
|
||||||
|
import "package:nexus/widgets/appbar.dart";
|
||||||
import "package:nexus/widgets/error_dialog.dart";
|
import "package:nexus/widgets/error_dialog.dart";
|
||||||
import "package:window_manager/window_manager.dart";
|
import "package:window_manager/window_manager.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
|
@ -59,7 +61,13 @@ void main() async {
|
||||||
setWindowMinSize(const Size.square(500));
|
setWindowMinSize(const Size.square(500));
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(observers: [if (kDebugMode) Logger()], child: const App()),
|
ProviderScope(
|
||||||
|
observers: [
|
||||||
|
// Change false to true if you want debug information on provider reloads
|
||||||
|
if (false && kDebugMode) Logger(),
|
||||||
|
],
|
||||||
|
child: const App(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +89,8 @@ class App extends ConsumerWidget {
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
))
|
))
|
||||||
.theme,
|
.theme,
|
||||||
home: ref
|
home: Builder(
|
||||||
|
builder: (context) => ref
|
||||||
.watch(SharedPrefsController.provider)
|
.watch(SharedPrefsController.provider)
|
||||||
.betterWhen(
|
.betterWhen(
|
||||||
data: (_) => ref
|
data: (_) => ref
|
||||||
|
|
@ -89,6 +98,32 @@ class App extends ConsumerWidget {
|
||||||
.betterWhen(
|
.betterWhen(
|
||||||
data: (client) =>
|
data: (client) =>
|
||||||
client.accessToken == null ? LoginPage() : ChatPage(),
|
client.accessToken == null ? LoginPage() : ChatPage(),
|
||||||
|
loading: () => Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
spacing: 16,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Syncing...",
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
|
),
|
||||||
|
CircularProgressIndicator(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
appBar: Appbar(
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(builder: (_) => SettingsPage()),
|
||||||
|
),
|
||||||
|
icon: Icon(Icons.settings),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,18 @@ import "dart:io";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter/services.dart";
|
import "package:flutter/services.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_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:fluttertagger/fluttertagger.dart";
|
import "package:fluttertagger/fluttertagger.dart";
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:matrix/matrix.dart";
|
import "package:matrix/matrix.dart";
|
||||||
|
import "package:nexus/controllers/avatar_controller.dart";
|
||||||
|
import "package:nexus/controllers/members_controller.dart";
|
||||||
import "package:nexus/controllers/room_chat_controller.dart";
|
import "package:nexus/controllers/room_chat_controller.dart";
|
||||||
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
|
import "package:nexus/helpers/extensions/get_headers.dart";
|
||||||
|
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||||
|
import "package:nexus/widgets/loading.dart";
|
||||||
|
|
||||||
class ChatBox extends HookConsumerWidget {
|
class ChatBox extends HookConsumerWidget {
|
||||||
final Message? replyToMessage;
|
final Message? replyToMessage;
|
||||||
|
|
@ -23,6 +30,8 @@ class ChatBox extends HookConsumerWidget {
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final controller = useRef(FlutterTaggerController());
|
final controller = useRef(FlutterTaggerController());
|
||||||
|
final triggerCharacter = useState("");
|
||||||
|
final query = useState("");
|
||||||
|
|
||||||
Future<void> send() => ref
|
Future<void> send() => ref
|
||||||
.watch(RoomChatController.provider(room).notifier)
|
.watch(RoomChatController.provider(room).notifier)
|
||||||
|
|
@ -54,11 +63,50 @@ class ChatBox extends HookConsumerWidget {
|
||||||
padding: EdgeInsetsGeometry.all(12),
|
padding: EdgeInsetsGeometry.all(12),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
child: Container(
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (replyToMessage != null)
|
||||||
|
Container(
|
||||||
|
color: theme.colorScheme.surfaceContainerHigh,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
child: Row(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Avatar(
|
||||||
|
userId: replyToMessage!.authorId,
|
||||||
|
headers: room.client.headers,
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
color: theme.colorScheme.surfaceContainerHighest,
|
color: theme.colorScheme.surfaceContainerHighest,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: // TODO: This doesn't work?
|
child: room.canSendDefaultMessages
|
||||||
room.canSendDefaultMessages
|
|
||||||
? Row(
|
? Row(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -68,16 +116,103 @@ class ChatBox extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FlutterTagger(
|
child: FlutterTagger(
|
||||||
overlay: SizedBox(),
|
triggerStrategy: TriggerStrategy.eager,
|
||||||
|
overlay: Padding(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(12),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
color:
|
||||||
|
theme.colorScheme.surfaceContainerHigh,
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: switch (triggerCharacter.value) {
|
||||||
|
"@" =>
|
||||||
|
ref
|
||||||
|
.watch(
|
||||||
|
MembersController.provider(room),
|
||||||
|
)
|
||||||
|
.betterWhen(
|
||||||
|
data: (members) => ListView(
|
||||||
|
children:
|
||||||
|
(query.value.isEmpty
|
||||||
|
? members
|
||||||
|
: members.where(
|
||||||
|
(member) =>
|
||||||
|
member
|
||||||
|
.senderId
|
||||||
|
.contains(
|
||||||
|
query
|
||||||
|
.value,
|
||||||
|
) ||
|
||||||
|
(member.content["displayname"]
|
||||||
|
as String?)
|
||||||
|
?.contains(
|
||||||
|
query.value,
|
||||||
|
) ==
|
||||||
|
true,
|
||||||
|
))
|
||||||
|
.map(
|
||||||
|
(member) => ListTile(
|
||||||
|
leading: AvatarOrHash(
|
||||||
|
ref
|
||||||
|
.watch(
|
||||||
|
AvatarController.provider(
|
||||||
|
member
|
||||||
|
.content["avatar_url"]
|
||||||
|
.toString(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.whenOrNull(
|
||||||
|
data:
|
||||||
|
(
|
||||||
|
data,
|
||||||
|
) =>
|
||||||
|
data,
|
||||||
|
),
|
||||||
|
member
|
||||||
|
.content["displayname"]
|
||||||
|
.toString(),
|
||||||
|
headers: room
|
||||||
|
.client
|
||||||
|
.headers,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
member.content["displayname"]
|
||||||
|
as String? ??
|
||||||
|
member
|
||||||
|
.senderId,
|
||||||
|
),
|
||||||
|
onTap: () => controller
|
||||||
|
.value
|
||||||
|
.addTag(
|
||||||
|
id: "member",
|
||||||
|
name: member
|
||||||
|
.senderId
|
||||||
|
.substring(
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.split(
|
||||||
|
":",
|
||||||
|
)
|
||||||
|
.first,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"#" => Text("Todo"),
|
||||||
|
_ => Loading(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
controller: controller.value,
|
controller: controller.value,
|
||||||
onSearch: (query, triggerCharacter) {
|
onSearch: (newQuery, newTriggerCharacter) {
|
||||||
triggerCharacter == "#";
|
triggerCharacter.value = newTriggerCharacter;
|
||||||
if (controller.value.tags.isEmpty) {
|
query.value = newQuery;
|
||||||
controller.value.addTag(
|
|
||||||
id: "id",
|
|
||||||
name: "name",
|
|
||||||
); // TODO: RM
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
triggerCharacterAndStyles: {
|
triggerCharacterAndStyles: {
|
||||||
"@": style,
|
"@": style,
|
||||||
|
|
@ -101,58 +236,11 @@ class ChatBox extends HookConsumerWidget {
|
||||||
IconButton(onPressed: send, icon: Icon(Icons.send)),
|
IconButton(onPressed: send, icon: Icon(Icons.send)),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Text("You don't have permission to send messages here..."),
|
: Text(
|
||||||
// Composer(
|
"You don't have permission to send messages here...",
|
||||||
// textEditingController: controller.value,
|
),
|
||||||
// key: key,
|
),
|
||||||
// sigmaY: 0,
|
],
|
||||||
// sendIconColor: theme.colorScheme.primary,
|
|
||||||
// sendOnEnter: true,
|
|
||||||
// topWidget: replyToMessage == null
|
|
||||||
// ? null
|
|
||||||
// : ColoredBox(
|
|
||||||
// color: theme.colorScheme.surfaceContainer,
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.symmetric(
|
|
||||||
// horizontal: 16,
|
|
||||||
// vertical: 4,
|
|
||||||
// ),
|
|
||||||
// child: Row(
|
|
||||||
// spacing: 8,
|
|
||||||
// children: [
|
|
||||||
// Avatar(
|
|
||||||
// userId: replyToMessage!.authorId,
|
|
||||||
// headers: room.client.headers,
|
|
||||||
// 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,
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue