Compare commits
3 Commits
b48a1aac44
...
3.2.0+129
Author | SHA1 | Date | |
---|---|---|---|
|
c9b71701c8 | ||
|
28e98488f1 | ||
|
b4d476613e |
@@ -944,5 +944,21 @@
|
|||||||
"unpinPostHint": "Are you sure you want to unpin this post?",
|
"unpinPostHint": "Are you sure you want to unpin this post?",
|
||||||
"all": "All",
|
"all": "All",
|
||||||
"statusPresent": "Present",
|
"statusPresent": "Present",
|
||||||
"accountAutomated": "Automated"
|
"accountAutomated": "Automated",
|
||||||
}
|
"chatBreakClearButton": "Clear",
|
||||||
|
"chatBreak5m": "5m",
|
||||||
|
"chatBreak10m": "10m",
|
||||||
|
"chatBreak15m": "15m",
|
||||||
|
"chatBreak30m": "30m",
|
||||||
|
"chatBreakCustomMinutes": "Custom (minutes)",
|
||||||
|
"chatBreakEnterMinutes": "Enter minutes",
|
||||||
|
"errorGeneric": "Error: {}",
|
||||||
|
"searchMessages": "Search Messages",
|
||||||
|
"messagesCount": "{} messages",
|
||||||
|
"dotSeparator": "·",
|
||||||
|
"roleValidationHint": "Role must be between 0 and 100",
|
||||||
|
"searchMessagesHint": "Search messages...",
|
||||||
|
"searchLinks": "Links",
|
||||||
|
"searchAttachments": "Attachments",
|
||||||
|
"noMessagesFound": "No messages found"
|
||||||
|
}
|
@@ -68,6 +68,10 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> getTotalMessagesForRoom(String roomId) {
|
||||||
|
return (select(chatMessages)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length);
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> searchMessages(
|
Future<List<LocalChatMessage>> searchMessages(
|
||||||
String roomId,
|
String roomId,
|
||||||
String query,
|
String query,
|
||||||
|
@@ -95,8 +95,24 @@ class LevelingScreen extends HookConsumerWidget {
|
|||||||
title: Text('levelingProgress'.tr()),
|
title: Text('levelingProgress'.tr()),
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(text: 'leveling'.tr()),
|
Tab(
|
||||||
Tab(text: 'stellarProgram'.tr()),
|
child: Text(
|
||||||
|
'leveling'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'stellarProgram'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -355,17 +355,20 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
offset: offset,
|
offset: offset,
|
||||||
limit: take,
|
limit: take,
|
||||||
);
|
);
|
||||||
dbMessages = chatMessagesFromDb.map(_database.companionToMessage).toList();
|
dbMessages =
|
||||||
|
chatMessagesFromDb.map(_database.companionToMessage).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<LocalChatMessage> filteredMessages = dbMessages;
|
List<LocalChatMessage> filteredMessages = dbMessages;
|
||||||
|
|
||||||
if (_withLinks == true) {
|
if (_withLinks == true) {
|
||||||
filteredMessages = filteredMessages.where((msg) => _hasLink(msg)).toList();
|
filteredMessages =
|
||||||
|
filteredMessages.where((msg) => _hasLink(msg)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_withAttachments == true) {
|
if (_withAttachments == true) {
|
||||||
filteredMessages = filteredMessages.where((msg) => _hasAttachment(msg)).toList();
|
filteredMessages =
|
||||||
|
filteredMessages.where((msg) => _hasAttachment(msg)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
final dbLocalMessages = filteredMessages;
|
final dbLocalMessages = filteredMessages;
|
||||||
@@ -513,7 +516,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
} finally {
|
} finally {
|
||||||
developer.log('Finished message sync', name: 'MessagesNotifier');
|
developer.log('Finished message sync', name: 'MessagesNotifier');
|
||||||
Future.microtask(() => ref.read(isSyncingProvider.notifier).state = false);
|
Future.microtask(
|
||||||
|
() => ref.read(isSyncingProvider.notifier).state = false,
|
||||||
|
);
|
||||||
_isSyncing = false;
|
_isSyncing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,7 +529,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
bool synced = false,
|
bool synced = false,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
if (offset == 0 && !synced && (_searchQuery == null || _searchQuery!.isEmpty)) {
|
if (offset == 0 &&
|
||||||
|
!synced &&
|
||||||
|
(_searchQuery == null || _searchQuery!.isEmpty)) {
|
||||||
_fetchAndCacheMessages(offset: 0, take: take).catchError((_) {
|
_fetchAndCacheMessages(offset: 0, take: take).catchError((_) {
|
||||||
return <LocalChatMessage>[];
|
return <LocalChatMessage>[];
|
||||||
});
|
});
|
||||||
@@ -584,7 +591,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_hasMore = false;
|
_hasMore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = AsyncValue.data(_sortMessages([...currentMessages, ...newMessages]));
|
state = AsyncValue.data(
|
||||||
|
_sortMessages([...currentMessages, ...newMessages]),
|
||||||
|
);
|
||||||
} catch (err, stackTrace) {
|
} catch (err, stackTrace) {
|
||||||
developer.log(
|
developer.log(
|
||||||
'Error loading more messages',
|
'Error loading more messages',
|
||||||
@@ -1481,12 +1490,6 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.search),
|
|
||||||
onPressed: () {
|
|
||||||
context.pushNamed('searchMessages', pathParameters: {'id': id});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
AudioCallButton(roomId: id),
|
AudioCallButton(roomId: id),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
@@ -1496,14 +1499,15 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
],
|
],
|
||||||
bottom: isSyncing
|
bottom:
|
||||||
? const PreferredSize(
|
isSyncing
|
||||||
preferredSize: Size.fromHeight(2),
|
? const PreferredSize(
|
||||||
child: LinearProgressIndicator(
|
preferredSize: Size.fromHeight(2),
|
||||||
borderRadius: BorderRadius.zero,
|
child: LinearProgressIndicator(
|
||||||
),
|
borderRadius: BorderRadius.zero,
|
||||||
)
|
),
|
||||||
: null,
|
)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
@@ -6,7 +6,7 @@ part of 'room.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$messagesNotifierHash() => r'dda98f5bf525f3b2bc0a7c89bc6eaa3c8b95f142';
|
String _$messagesNotifierHash() => r'fc3b66dfb8dd3fc55d142dae5c5e7bdc67eca5d4';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
@@ -20,10 +20,17 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:island/pods/database.dart';
|
||||||
|
|
||||||
part 'room_detail.freezed.dart';
|
part 'room_detail.freezed.dart';
|
||||||
part 'room_detail.g.dart';
|
part 'room_detail.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<int> totalMessagesCount(Ref ref, String roomId) async {
|
||||||
|
final database = ref.watch(databaseProvider);
|
||||||
|
return database.getTotalMessagesForRoom(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
class ChatDetailScreen extends HookConsumerWidget {
|
class ChatDetailScreen extends HookConsumerWidget {
|
||||||
final String id;
|
final String id;
|
||||||
const ChatDetailScreen({super.key, required this.id});
|
const ChatDetailScreen({super.key, required this.id});
|
||||||
@@ -32,6 +39,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final roomState = ref.watch(chatroomProvider(id));
|
final roomState = ref.watch(chatroomProvider(id));
|
||||||
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
||||||
|
final totalMessages = ref.watch(totalMessagesCountProvider(id));
|
||||||
|
|
||||||
const kNotifyLevelText = [
|
const kNotifyLevelText = [
|
||||||
'chatNotifyLevelAll',
|
'chatNotifyLevelAll',
|
||||||
@@ -132,7 +140,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
const Text('chatBreakDescription').tr(),
|
const Text('chatBreakDescription').tr(),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Clear').tr(),
|
title: const Text('chatBreakClearButton').tr(),
|
||||||
subtitle: const Text('chatBreakClear').tr(),
|
subtitle: const Text('chatBreakClear').tr(),
|
||||||
leading: const Icon(Icons.notifications_active),
|
leading: const Icon(Icons.notifications_active),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -144,8 +152,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('5m'),
|
title: const Text('chatBreak5m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['5m']),
|
subtitle: const Text('chatBreakHour').tr(args: ['chatBreak5m'.tr()]),
|
||||||
leading: const Icon(Symbols.circle),
|
leading: const Icon(Symbols.circle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 5)));
|
setChatBreak(now.add(const Duration(minutes: 5)));
|
||||||
@@ -156,8 +164,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('10m'),
|
title: const Text('chatBreak10m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['10m']),
|
subtitle: const Text('chatBreakHour').tr(args: ['chatBreak10m'.tr()]),
|
||||||
leading: const Icon(Symbols.circle),
|
leading: const Icon(Symbols.circle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 10)));
|
setChatBreak(now.add(const Duration(minutes: 10)));
|
||||||
@@ -168,8 +176,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('15m'),
|
title: const Text('chatBreak15m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['15m']),
|
subtitle: const Text('chatBreakHour').tr(args: ['chatBreak15m'.tr()]),
|
||||||
leading: const Icon(Symbols.timer_3),
|
leading: const Icon(Symbols.timer_3),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 15)));
|
setChatBreak(now.add(const Duration(minutes: 15)));
|
||||||
@@ -180,8 +188,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('30m'),
|
title: const Text('chatBreak30m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['30m']),
|
subtitle: const Text('chatBreakHour').tr(args: ['chatBreak30m'.tr()]),
|
||||||
leading: const Icon(Symbols.timer),
|
leading: const Icon(Symbols.timer),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 30)));
|
setChatBreak(now.add(const Duration(minutes: 30)));
|
||||||
@@ -195,8 +203,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
TextField(
|
TextField(
|
||||||
controller: durationController,
|
controller: durationController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Custom (minutes)'.tr(),
|
labelText: 'chatBreakCustomMinutes'.tr(),
|
||||||
hintText: 'Enter minutes'.tr(),
|
hintText: 'chatBreakEnterMinutes'.tr(),
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
icon: const Icon(Icons.check),
|
icon: const Icon(Icons.check),
|
||||||
@@ -239,7 +247,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
body: roomState.when(
|
body: roomState.when(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, _) => Center(child: Text('Error: $error')),
|
error: (error, _) => Center(child: Text('errorGeneric'.tr(args: [error.toString()]))),
|
||||||
data:
|
data:
|
||||||
(currentRoom) => CustomScrollView(
|
(currentRoom) => CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
@@ -365,7 +373,12 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
leading: const Icon(Icons.search),
|
leading: const Icon(Icons.search),
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
title: const Text('Search Messages').tr(),
|
title: const Text('searchMessages').tr(),
|
||||||
|
subtitle: totalMessages.when(
|
||||||
|
data: (count) => Text('messagesCount'.tr(args: [count.toString()])),
|
||||||
|
loading: () => const CircularProgressIndicator(),
|
||||||
|
error: (err, stack) => Text('errorGeneric'.tr(args: [err.toString()])),
|
||||||
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed('searchMessages', pathParameters: {'id': id});
|
context.pushNamed('searchMessages', pathParameters: {'id': id});
|
||||||
},
|
},
|
||||||
@@ -703,7 +716,7 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
? 'permissionModerator'
|
? 'permissionModerator'
|
||||||
: 'permissionMember',
|
: 'permissionMember',
|
||||||
).tr(),
|
).tr(),
|
||||||
Text('·').bold().padding(horizontal: 6),
|
Text('dotSeparator').bold().padding(horizontal: 6),
|
||||||
Expanded(child: Text("@${member.account.name}")),
|
Expanded(child: Text("@${member.account.name}")),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -863,7 +876,7 @@ class _ChatMemberRoleSheet extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
final newRole = int.parse(roleController.text);
|
final newRole = int.parse(roleController.text);
|
||||||
if (newRole < 0 || newRole > 100) {
|
if (newRole < 0 || newRole > 100) {
|
||||||
throw 'Role must be between 0 and 100';
|
throw 'roleValidationHint'.tr();
|
||||||
}
|
}
|
||||||
|
|
||||||
final apiClient = ref.read(apiClientProvider);
|
final apiClient = ref.read(apiClientProvider);
|
||||||
|
@@ -6,8 +6,8 @@ part of 'room_detail.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$chatMemberListNotifierHash() =>
|
String _$totalMessagesCountHash() =>
|
||||||
r'3ea30150278523e9f6b23f9200ea9a9fbae9c973';
|
r'a15c03461f25c2d4d39c0926509bf626ae2550a6';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -30,6 +30,128 @@ class _SystemHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
@ProviderFor(totalMessagesCount)
|
||||||
|
const totalMessagesCountProvider = TotalMessagesCountFamily();
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
class TotalMessagesCountFamily extends Family<AsyncValue<int>> {
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
const TotalMessagesCountFamily();
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
TotalMessagesCountProvider call(String roomId) {
|
||||||
|
return TotalMessagesCountProvider(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TotalMessagesCountProvider getProviderOverride(
|
||||||
|
covariant TotalMessagesCountProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'totalMessagesCountProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
class TotalMessagesCountProvider extends AutoDisposeFutureProvider<int> {
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
TotalMessagesCountProvider(String roomId)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => totalMessagesCount(ref as TotalMessagesCountRef, roomId),
|
||||||
|
from: totalMessagesCountProvider,
|
||||||
|
name: r'totalMessagesCountProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$totalMessagesCountHash,
|
||||||
|
dependencies: TotalMessagesCountFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
TotalMessagesCountFamily._allTransitiveDependencies,
|
||||||
|
roomId: roomId,
|
||||||
|
);
|
||||||
|
|
||||||
|
TotalMessagesCountProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.roomId,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String roomId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<int> Function(TotalMessagesCountRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: TotalMessagesCountProvider._internal(
|
||||||
|
(ref) => create(ref as TotalMessagesCountRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
roomId: roomId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<int> createElement() {
|
||||||
|
return _TotalMessagesCountProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is TotalMessagesCountProvider && other.roomId == roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, roomId.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin TotalMessagesCountRef on AutoDisposeFutureProviderRef<int> {
|
||||||
|
/// The parameter `roomId` of this provider.
|
||||||
|
String get roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TotalMessagesCountProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<int>
|
||||||
|
with TotalMessagesCountRef {
|
||||||
|
_TotalMessagesCountProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get roomId => (origin as TotalMessagesCountProvider).roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$chatMemberListNotifierHash() =>
|
||||||
|
r'3ea30150278523e9f6b23f9200ea9a9fbae9c973';
|
||||||
|
|
||||||
abstract class _$ChatMemberListNotifier
|
abstract class _$ChatMemberListNotifier
|
||||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> {
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> {
|
||||||
late final String roomId;
|
late final String roomId;
|
||||||
|
@@ -32,7 +32,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Search Messages')),
|
appBar: AppBar(title: const Text('searchMessages').tr()),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
@@ -40,7 +40,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
|||||||
TextField(
|
TextField(
|
||||||
controller: searchController,
|
controller: searchController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Search messages...',
|
hintText: 'searchMessagesHint'.tr(),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
isDense: true,
|
isDense: true,
|
||||||
contentPadding: EdgeInsets.only(
|
contentPadding: EdgeInsets.only(
|
||||||
@@ -72,7 +72,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: CheckboxListTile(
|
child: CheckboxListTile(
|
||||||
secondary: const Icon(Symbols.link),
|
secondary: const Icon(Symbols.link),
|
||||||
title: const Text('Links'),
|
title: const Text('searchLinks').tr(),
|
||||||
value: withLinks.value,
|
value: withLinks.value,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
withLinks.value = value!;
|
withLinks.value = value!;
|
||||||
@@ -87,7 +87,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: CheckboxListTile(
|
child: CheckboxListTile(
|
||||||
secondary: const Icon(Symbols.file_copy),
|
secondary: const Icon(Symbols.file_copy),
|
||||||
title: const Text('Attachments'),
|
title: const Text('searchAttachments').tr(),
|
||||||
value: withAttachments.value,
|
value: withAttachments.value,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
withAttachments.value = value!;
|
withAttachments.value = value!;
|
||||||
@@ -109,7 +109,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
|||||||
data:
|
data:
|
||||||
(messageList) =>
|
(messageList) =>
|
||||||
messageList.isEmpty
|
messageList.isEmpty
|
||||||
? Center(child: Text('No messages found'.tr()))
|
? Center(child: Text('noMessagesFound'.tr()))
|
||||||
: SuperListView.builder(
|
: SuperListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
reverse: true, // Show newest messages at the bottom
|
reverse: true, // Show newest messages at the bottom
|
||||||
@@ -129,7 +129,7 @@ class SearchMessagesScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, _) => Center(child: Text('Error: $error')),
|
error: (error, _) => Center(child: Text('errorGeneric'.tr(args: [error.toString()]))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@@ -27,7 +27,9 @@ class AppDetailScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final tabController = useTabController(initialLength: 2);
|
final tabController = useTabController(initialLength: 2);
|
||||||
final appData = ref.watch(customAppProvider(publisherName, projectId, appId));
|
final appData = ref.watch(
|
||||||
|
customAppProvider(publisherName, projectId, appId),
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -35,23 +37,43 @@ class AppDetailScreen extends HookConsumerWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.edit),
|
icon: const Icon(Symbols.edit),
|
||||||
onPressed: appData.value == null
|
onPressed:
|
||||||
? null
|
appData.value == null
|
||||||
: () {
|
? null
|
||||||
context.pushNamed(
|
: () {
|
||||||
'developerAppEdit',
|
context.pushNamed(
|
||||||
pathParameters: {
|
'developerAppEdit',
|
||||||
'name': publisherName,
|
pathParameters: {
|
||||||
'projectId': projectId,
|
'name': publisherName,
|
||||||
'id': appId,
|
'projectId': projectId,
|
||||||
},
|
'id': appId,
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [Tab(text: 'overview'.tr()), Tab(text: 'secrets'.tr())],
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'overview'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'secrets'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: appData.when(
|
body: appData.when(
|
||||||
@@ -70,12 +92,14 @@ class AppDetailScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (err, stack) => ResponseErrorWidget(
|
error:
|
||||||
error: err,
|
(err, stack) => ResponseErrorWidget(
|
||||||
onRetry: () => ref.invalidate(
|
error: err,
|
||||||
customAppProvider(publisherName, projectId, appId),
|
onRetry:
|
||||||
),
|
() => ref.invalidate(
|
||||||
),
|
customAppProvider(publisherName, projectId, appId),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -98,12 +122,13 @@ class _AppOverview extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
child: app.background != null
|
child:
|
||||||
? CloudFileWidget(
|
app.background != null
|
||||||
item: app.background!,
|
? CloudFileWidget(
|
||||||
fit: BoxFit.cover,
|
item: app.background!,
|
||||||
)
|
fit: BoxFit.cover,
|
||||||
: const SizedBox.shrink(),
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 20,
|
left: 20,
|
||||||
|
@@ -52,7 +52,26 @@ class BotDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [Tab(text: 'overview'.tr()), Tab(text: 'keys'.tr())],
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'overview'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'keys'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: botData.when(
|
body: botData.when(
|
||||||
|
@@ -58,7 +58,26 @@ class ProjectDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [Tab(text: 'customApps'.tr()), Tab(text: 'bots'.tr())],
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'customApps'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'bots'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: TabBarView(
|
body: TabBarView(
|
||||||
|
@@ -143,8 +143,26 @@ class ArticlesScreen extends ConsumerWidget {
|
|||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
tabs: [
|
tabs: [
|
||||||
const Tab(text: 'All'),
|
Tab(
|
||||||
...feeds.map((feed) => Tab(text: feed.title)),
|
child: Text(
|
||||||
|
'All',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...feeds.map(
|
||||||
|
(feed) => Tab(
|
||||||
|
child: Text(
|
||||||
|
feed.title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 3.2.0+128
|
version: 3.2.0+129
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
@@ -139,6 +139,7 @@ dependencies:
|
|||||||
material_color_utilities: ^0.11.1
|
material_color_utilities: ^0.11.1
|
||||||
screenshot: ^3.0.0
|
screenshot: ^3.0.0
|
||||||
flutter_card_swiper: ^7.0.2
|
flutter_card_swiper: ^7.0.2
|
||||||
|
file_saver: ^0.3.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -235,4 +236,5 @@ msix_config:
|
|||||||
identity_name: dev.solian.app
|
identity_name: dev.solian.app
|
||||||
msix_version: 3.2.0.0
|
msix_version: 3.2.0.0
|
||||||
logo_path: .\assets\icons\icon.png
|
logo_path: .\assets\icons\icon.png
|
||||||
capabilities: internetClientServer, location, microphone, webcam
|
capabilities: internetClientServer, location, microphone, webcam
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user