✨ Chat rooms in realm detail page
This commit is contained in:
parent
180fbcc558
commit
f511612a53
@ -1,6 +1,8 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:island/screens/chat/chat.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
@ -44,6 +46,13 @@ Future<SnRealmMember?> realmIdentity(Ref ref, String realmSlug) async {
|
|||||||
return SnRealmMember.fromJson(response.data);
|
return SnRealmMember.fromJson(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<List<SnChatRoom>> realmChatRooms(Ref ref, String realmSlug) async {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final response = await apiClient.get('/realms/$realmSlug/chat');
|
||||||
|
return (response.data as List).map((e) => SnChatRoom.fromJson(e)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
class RealmDetailScreen extends HookConsumerWidget {
|
class RealmDetailScreen extends HookConsumerWidget {
|
||||||
final String slug;
|
final String slug;
|
||||||
|
|
||||||
@ -111,59 +120,94 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: ref
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
.watch(realmIdentityProvider(slug))
|
||||||
children: [
|
.when(
|
||||||
ref
|
loading: () => const SizedBox.shrink(),
|
||||||
.watch(realmIdentityProvider(slug))
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
.when(
|
data:
|
||||||
loading: () => const SizedBox.shrink(),
|
(identity) => Column(
|
||||||
error: (_, _) => const SizedBox.shrink(),
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
data:
|
children: [
|
||||||
(identity) => Column(
|
ExpansionTile(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
title: const Text('description').tr(),
|
||||||
|
initiallyExpanded: identity == null,
|
||||||
|
tilePadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
),
|
||||||
children: [
|
children: [
|
||||||
ExpansionTile(
|
Text(
|
||||||
title: const Text('description').tr(),
|
realm.description,
|
||||||
initiallyExpanded: identity == null,
|
style: const TextStyle(fontSize: 16),
|
||||||
children: [
|
).padding(
|
||||||
Text(
|
horizontal: 16,
|
||||||
realm.description,
|
bottom: 16,
|
||||||
style: const TextStyle(fontSize: 16),
|
top: 8,
|
||||||
).padding(horizontal: 16, vertical: 16),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const Gap(4),
|
|
||||||
if (identity != null && realm.isPublic)
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: () async {
|
|
||||||
try {
|
|
||||||
final apiClient = ref.read(
|
|
||||||
apiClientProvider,
|
|
||||||
);
|
|
||||||
await apiClient.post(
|
|
||||||
'/realms/$slug/members/me',
|
|
||||||
);
|
|
||||||
ref.invalidate(
|
|
||||||
realmIdentityProvider(slug),
|
|
||||||
);
|
|
||||||
ref.invalidate(
|
|
||||||
realmsJoinedProvider,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.add),
|
|
||||||
label: const Text('joinRealm').tr(),
|
|
||||||
).padding(horizontal: 16)
|
|
||||||
else
|
|
||||||
const SizedBox.shrink(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (identity == null && realm.isPublic)
|
||||||
|
FilledButton.tonalIcon(
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
final apiClient = ref.read(
|
||||||
|
apiClientProvider,
|
||||||
|
);
|
||||||
|
await apiClient.post(
|
||||||
|
'/realms/$slug/members/me',
|
||||||
|
);
|
||||||
|
ref.invalidate(
|
||||||
|
realmIdentityProvider(slug),
|
||||||
|
);
|
||||||
|
ref.invalidate(realmsJoinedProvider);
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.add),
|
||||||
|
label: const Text('joinRealm').tr(),
|
||||||
|
).padding(horizontal: 16, vertical: 4)
|
||||||
|
else
|
||||||
|
const SizedBox.shrink(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SliverToBoxAdapter(child: Divider(height: 1)),
|
||||||
|
Consumer(
|
||||||
|
builder: (context, ref, _) {
|
||||||
|
final chatRooms = ref.watch(realmChatRoomsProvider(slug));
|
||||||
|
return chatRooms.when(
|
||||||
|
loading:
|
||||||
|
() => const SliverToBoxAdapter(
|
||||||
|
child: Center(child: CircularProgressIndicator()),
|
||||||
),
|
),
|
||||||
],
|
error:
|
||||||
),
|
(error, _) => SliverToBoxAdapter(
|
||||||
|
child: Center(child: Text('Error: $error')),
|
||||||
|
),
|
||||||
|
data: (rooms) {
|
||||||
|
if (rooms.isEmpty) {
|
||||||
|
return const SliverToBoxAdapter(
|
||||||
|
child: SizedBox.shrink(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate((
|
||||||
|
context,
|
||||||
|
index,
|
||||||
|
) {
|
||||||
|
return ChatRoomListTile(
|
||||||
|
room: rooms[index],
|
||||||
|
onTap: () {
|
||||||
|
context.push('/chat/${rooms[index].id}');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}, childCount: rooms.length),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -276,6 +276,128 @@ class _RealmIdentityProviderElement
|
|||||||
String get realmSlug => (origin as RealmIdentityProvider).realmSlug;
|
String get realmSlug => (origin as RealmIdentityProvider).realmSlug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$realmChatRoomsHash() => r'8207c1e6f0922323967f208efeed027e943039cc';
|
||||||
|
|
||||||
|
/// See also [realmChatRooms].
|
||||||
|
@ProviderFor(realmChatRooms)
|
||||||
|
const realmChatRoomsProvider = RealmChatRoomsFamily();
|
||||||
|
|
||||||
|
/// See also [realmChatRooms].
|
||||||
|
class RealmChatRoomsFamily extends Family<AsyncValue<List<SnChatRoom>>> {
|
||||||
|
/// See also [realmChatRooms].
|
||||||
|
const RealmChatRoomsFamily();
|
||||||
|
|
||||||
|
/// See also [realmChatRooms].
|
||||||
|
RealmChatRoomsProvider call(String realmSlug) {
|
||||||
|
return RealmChatRoomsProvider(realmSlug);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
RealmChatRoomsProvider getProviderOverride(
|
||||||
|
covariant RealmChatRoomsProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.realmSlug);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'realmChatRoomsProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [realmChatRooms].
|
||||||
|
class RealmChatRoomsProvider
|
||||||
|
extends AutoDisposeFutureProvider<List<SnChatRoom>> {
|
||||||
|
/// See also [realmChatRooms].
|
||||||
|
RealmChatRoomsProvider(String realmSlug)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => realmChatRooms(ref as RealmChatRoomsRef, realmSlug),
|
||||||
|
from: realmChatRoomsProvider,
|
||||||
|
name: r'realmChatRoomsProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$realmChatRoomsHash,
|
||||||
|
dependencies: RealmChatRoomsFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
RealmChatRoomsFamily._allTransitiveDependencies,
|
||||||
|
realmSlug: realmSlug,
|
||||||
|
);
|
||||||
|
|
||||||
|
RealmChatRoomsProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.realmSlug,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String realmSlug;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<List<SnChatRoom>> Function(RealmChatRoomsRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: RealmChatRoomsProvider._internal(
|
||||||
|
(ref) => create(ref as RealmChatRoomsRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
realmSlug: realmSlug,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<List<SnChatRoom>> createElement() {
|
||||||
|
return _RealmChatRoomsProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is RealmChatRoomsProvider && other.realmSlug == realmSlug;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, realmSlug.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin RealmChatRoomsRef on AutoDisposeFutureProviderRef<List<SnChatRoom>> {
|
||||||
|
/// The parameter `realmSlug` of this provider.
|
||||||
|
String get realmSlug;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RealmChatRoomsProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<List<SnChatRoom>>
|
||||||
|
with RealmChatRoomsRef {
|
||||||
|
_RealmChatRoomsProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get realmSlug => (origin as RealmChatRoomsProvider).realmSlug;
|
||||||
|
}
|
||||||
|
|
||||||
String _$realmMemberListNotifierHash() =>
|
String _$realmMemberListNotifierHash() =>
|
||||||
r'b2e3eefc62a597f45df9470b2058fdda62f8853f';
|
r'b2e3eefc62a597f45df9470b2058fdda62f8853f';
|
||||||
|
|
||||||
|
@ -233,16 +233,27 @@ class MessageItem extends HookConsumerWidget {
|
|||||||
if (remoteMessage.meta['embeds'] != null)
|
if (remoteMessage.meta['embeds'] != null)
|
||||||
...((remoteMessage.meta['embeds'] as List<dynamic>)
|
...((remoteMessage.meta['embeds'] as List<dynamic>)
|
||||||
.where((embed) => embed['Type'] == 'link')
|
.where((embed) => embed['Type'] == 'link')
|
||||||
.map((embed) => SnEmbedLink.fromJson(embed as Map<String, dynamic>))
|
.map(
|
||||||
.map((link) => LayoutBuilder(
|
(embed) => SnEmbedLink.fromJson(
|
||||||
builder: (context, constraints) {
|
embed as Map<String, dynamic>,
|
||||||
return EmbedLinkWidget(
|
),
|
||||||
link: link,
|
)
|
||||||
maxWidth: math.min(constraints.maxWidth, 480),
|
.map(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 4),
|
(link) => LayoutBuilder(
|
||||||
);
|
builder: (context, constraints) {
|
||||||
},
|
return EmbedLinkWidget(
|
||||||
))
|
link: link,
|
||||||
|
maxWidth: math.min(
|
||||||
|
constraints.maxWidth,
|
||||||
|
480,
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.symmetric(
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
.toList()),
|
.toList()),
|
||||||
if (progress != null && progress!.isNotEmpty)
|
if (progress != null && progress!.isNotEmpty)
|
||||||
Column(
|
Column(
|
||||||
@ -482,7 +493,11 @@ class _MessageItemContent extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
case 'text':
|
case 'text':
|
||||||
default:
|
default:
|
||||||
return MarkdownTextContent(content: item.content!, isSelectable: true);
|
return MarkdownTextContent(
|
||||||
|
content: item.content!,
|
||||||
|
isSelectable: true,
|
||||||
|
linesMargin: EdgeInsets.zero,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user