pretty cool
This commit is contained in:
parent
b42081b525
commit
40bad1e06e
7 changed files with 539 additions and 53 deletions
33
lib/controllers/client_controller.dart
Normal file
33
lib/controllers/client_controller.dart
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import "dart:io";
|
||||
|
||||
import "package:matrix/matrix.dart";
|
||||
import "package:nexusbot/controllers/settings_controller.dart";
|
||||
import "package:riverpod/riverpod.dart";
|
||||
import "package:sqflite_common_ffi/sqflite_ffi.dart";
|
||||
|
||||
class ClientController extends AsyncNotifier<Client> {
|
||||
@override
|
||||
Future<Client> build() async {
|
||||
final settings = ref.watch(SettingsController.provider)!;
|
||||
final client = Client(
|
||||
"nexusbot",
|
||||
database: await MatrixSdkDatabase.init(
|
||||
"NexusBot",
|
||||
database: await databaseFactoryFfi.openDatabase(inMemoryDatabasePath),
|
||||
),
|
||||
);
|
||||
|
||||
await client.checkHomeserver(settings.homeserver);
|
||||
await client.login(
|
||||
LoginType.mLoginPassword,
|
||||
identifier: AuthenticationUserIdentifier(user: settings.name),
|
||||
password: (await File(settings.botPasswordFile).readAsString()).trim(),
|
||||
);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<ClientController, Client>(
|
||||
ClientController.new,
|
||||
);
|
||||
}
|
||||
48
lib/controllers/room_chat_controller.dart
Normal file
48
lib/controllers/room_chat_controller.dart
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class RoomChatController extends Notifier<ChatController> {
|
||||
RoomChatController(this.id);
|
||||
final String id;
|
||||
|
||||
@override
|
||||
InMemoryChatController build() => InMemoryChatController(
|
||||
messages: [
|
||||
Message.text(id: "foo2", authorId: "foo", text: "**Some** text"),
|
||||
Message.text(
|
||||
id: "foo3",
|
||||
authorId: "foo5",
|
||||
text: "Some text 2 https://federated.nexus",
|
||||
),
|
||||
Message.text(
|
||||
id: "aksdjflkasdjf",
|
||||
authorId: "foo",
|
||||
text: "Some text 2 https://github.com/Henry-hiles/nixos",
|
||||
),
|
||||
Message.system(id: "foo4", authorId: "", text: "system"),
|
||||
Message.text(id: "foo6", authorId: "foo5", text: "Some text 2"),
|
||||
Message.image(
|
||||
id: "foo5",
|
||||
authorId: "foobar3",
|
||||
source:
|
||||
"https://henryhiles.com/_astro/federatedNexus.BvZmkdyc_2b28Im.webp",
|
||||
),
|
||||
Message.text(id: "foo7", authorId: "foobar3", text: "this has an image"),
|
||||
],
|
||||
);
|
||||
|
||||
void send(String message) {
|
||||
state.insertMessage(
|
||||
Message.text(
|
||||
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
authorId: "foo",
|
||||
text: message,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static final provider =
|
||||
NotifierProvider.family<RoomChatController, ChatController, String>(
|
||||
RoomChatController.new,
|
||||
);
|
||||
}
|
||||
107
lib/main.dart
107
lib/main.dart
|
|
@ -1,8 +1,10 @@
|
|||
import "dart:io";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/widgets/room_chat.dart";
|
||||
import "package:nexus/widgets/sidebar.dart";
|
||||
import "package:window_manager/window_manager.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:dynamic_system_colors/dynamic_system_colors.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
import "package:window_size/window_size.dart";
|
||||
|
||||
void main() async {
|
||||
|
|
@ -15,65 +17,66 @@ void main() async {
|
|||
|
||||
setWindowMinSize(const Size.square(500));
|
||||
|
||||
runApp(const App());
|
||||
runApp(ProviderScope(child: const App()));
|
||||
}
|
||||
|
||||
class App extends HookWidget {
|
||||
class App extends StatelessWidget {
|
||||
const App({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final index = useState(0);
|
||||
final drawer = Drawer(
|
||||
child: Row(
|
||||
children: [
|
||||
NavigationRail(
|
||||
useIndicator: false,
|
||||
labelType: NavigationRailLabelType.none,
|
||||
onDestinationSelected: (value) => index.value = value,
|
||||
destinations: [
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.home),
|
||||
label: Text("Home"),
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Image.file(File("assets/icon.png"), width: 35),
|
||||
label: Text("Space 1"),
|
||||
),
|
||||
],
|
||||
selectedIndex: index.value,
|
||||
Widget build(BuildContext context) => DynamicColorBuilder(
|
||||
builder: (lightDynamic, darkDynamic) => LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isDesktop = constraints.maxWidth > 650;
|
||||
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData.from(
|
||||
colorScheme:
|
||||
lightDynamic ?? ColorScheme.fromSeed(seedColor: Colors.indigo),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
return DynamicColorBuilder(
|
||||
builder: (lightDynamic, darkDynamic) => LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isDesktop = constraints.maxWidth > 650;
|
||||
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData.from(
|
||||
colorScheme: lightDynamic ?? ColorScheme.light(),
|
||||
),
|
||||
darkTheme: ThemeData.from(
|
||||
colorScheme: darkDynamic ?? ColorScheme.dark(),
|
||||
),
|
||||
home: Scaffold(
|
||||
appBar: isDesktop ? null : AppBar(),
|
||||
body: Row(
|
||||
darkTheme: ThemeData.from(
|
||||
colorScheme:
|
||||
darkDynamic ??
|
||||
ColorScheme.fromSeed(
|
||||
seedColor: Colors.indigo,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
),
|
||||
home: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => Row(
|
||||
children: [
|
||||
if (isDesktop) drawer,
|
||||
Expanded(child: Column()),
|
||||
if (isDesktop) Sidebar(),
|
||||
Expanded(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: isDesktop
|
||||
? null
|
||||
: DrawerButton(
|
||||
onPressed: () =>
|
||||
Scaffold.of(context).openDrawer(),
|
||||
),
|
||||
actionsPadding: EdgeInsets.symmetric(horizontal: 8),
|
||||
title: Text("Some Chat Name"),
|
||||
actions: [
|
||||
if (!(Platform.isAndroid || Platform.isIOS))
|
||||
IconButton(
|
||||
onPressed: () => exit(0),
|
||||
icon: Icon(Icons.close),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: RoomChat(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
drawer: isDesktop ? null : drawer,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
drawer: isDesktop ? null : Sidebar(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
89
lib/widgets/room_chat.dart
Normal file
89
lib/widgets/room_chat.dart
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||
import "package:flutter_chat_ui/flutter_chat_ui.dart";
|
||||
import "package:flutter_link_previewer/flutter_link_previewer.dart";
|
||||
import "package:flyer_chat_image_message/flyer_chat_image_message.dart";
|
||||
import "package:flyer_chat_system_message/flyer_chat_system_message.dart";
|
||||
import "package:flyer_chat_text_message/flyer_chat_text_message.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/controllers/room_chat_controller.dart";
|
||||
|
||||
class RoomChat extends HookConsumerWidget {
|
||||
const RoomChat({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final controller = RoomChatController.provider("1");
|
||||
final theme = Theme.of(context);
|
||||
return Chat(
|
||||
currentUserId: "foo",
|
||||
theme: ChatTheme.fromThemeData(theme).copyWith(
|
||||
colors: ChatColors.fromThemeData(theme).copyWith(
|
||||
primary: theme.colorScheme.primaryContainer,
|
||||
onPrimary: theme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
),
|
||||
builders: Builders(
|
||||
composerBuilder: (_) => Composer(),
|
||||
textMessageBuilder:
|
||||
(
|
||||
context,
|
||||
message,
|
||||
index, {
|
||||
required bool isSentByMe,
|
||||
MessageGroupStatus? groupStatus,
|
||||
}) => FlyerChatTextMessage(
|
||||
message: message.copyWith(
|
||||
text: message.text.replaceAllMapped(
|
||||
RegExp(
|
||||
r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+",
|
||||
),
|
||||
(match) => "[${match.group(0)}](${match.group(0)})",
|
||||
),
|
||||
),
|
||||
index: index,
|
||||
linksDecoration: TextDecoration.underline,
|
||||
),
|
||||
linkPreviewBuilder: (_, message, isSentByMe) {
|
||||
return LinkPreview(
|
||||
text: message.text,
|
||||
backgroundColor: isSentByMe
|
||||
? theme.colorScheme.inversePrimary
|
||||
: theme.colorScheme.surfaceContainerLow,
|
||||
insidePadding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
linkPreviewData: message.linkPreviewData,
|
||||
onLinkPreviewDataFetched: (linkPreviewData) {
|
||||
ref
|
||||
.watch(controller)
|
||||
.updateMessage(
|
||||
message,
|
||||
message.copyWith(linkPreviewData: linkPreviewData),
|
||||
);
|
||||
},
|
||||
// You can still customize the appearance
|
||||
parentContent: message.text,
|
||||
);
|
||||
},
|
||||
imageMessageBuilder:
|
||||
(
|
||||
_,
|
||||
message,
|
||||
index, {
|
||||
required bool isSentByMe,
|
||||
MessageGroupStatus? groupStatus,
|
||||
}) => FlyerChatImageMessage(message: message, index: index),
|
||||
systemMessageBuilder:
|
||||
(
|
||||
_,
|
||||
message,
|
||||
index, {
|
||||
required bool isSentByMe,
|
||||
MessageGroupStatus? groupStatus,
|
||||
}) => FlyerChatSystemMessage(message: message, index: index),
|
||||
),
|
||||
onMessageSend: ref.watch(controller.notifier).send,
|
||||
resolveUser: (id) async => User(id: id, imageSource: "foo"),
|
||||
chatController: ref.watch(controller),
|
||||
);
|
||||
}
|
||||
}
|
||||
75
lib/widgets/sidebar.dart
Normal file
75
lib/widgets/sidebar.dart
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import "dart:io";
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
|
||||
class Sidebar extends HookWidget {
|
||||
const Sidebar({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final index = useState(0);
|
||||
return Drawer(
|
||||
shape: Border(),
|
||||
child: Row(
|
||||
children: [
|
||||
NavigationRail(
|
||||
useIndicator: false,
|
||||
labelType: NavigationRailLabelType.none,
|
||||
onDestinationSelected: (value) => index.value = value,
|
||||
destinations: [
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.home),
|
||||
label: Text("Home"),
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.person),
|
||||
label: Text("Messages"),
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Image.file(File("assets/icon.png"), width: 40),
|
||||
label: Text("Space 1"),
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
),
|
||||
],
|
||||
selectedIndex: index.value,
|
||||
),
|
||||
Expanded(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
appBar: AppBar(
|
||||
title: Text("Some Space"),
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
body: NavigationRail(
|
||||
backgroundColor: Colors.transparent,
|
||||
extended: true,
|
||||
destinations: [
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.numbers),
|
||||
label: Text("Room 1"),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.numbers),
|
||||
label: Text("Room 2"),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.numbers),
|
||||
label: Text("Room 3"),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.numbers),
|
||||
label: Text("Room 4"),
|
||||
),
|
||||
],
|
||||
selectedIndex: 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue