parent
a54004736b
commit
0fcbc275cd
5 changed files with 326 additions and 1 deletions
|
|
@ -320,6 +320,11 @@ class ClientController extends AsyncNotifier<int> {
|
|||
|
||||
Future<void> logout() => _sendCommand("logout");
|
||||
|
||||
Future<void> setTyping(String roomId, Duration timeout) => _sendCommand(
|
||||
"set_typing",
|
||||
{"room_id": roomId, "timeout": timeout.inMilliseconds},
|
||||
);
|
||||
|
||||
Future<void> markRead(Room room) async {
|
||||
if (room.timeline.isEmpty || room.metadata == null) return;
|
||||
final eventRowId = room.timeline[room.timeline.keys.reduce(max)];
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import "package:nexus/controllers/rooms.dart";
|
|||
import "package:nexus/controllers/space_edges.dart";
|
||||
import "package:nexus/controllers/sync_status.dart";
|
||||
import "package:nexus/controllers/top_level_spaces.dart";
|
||||
import "package:nexus/controllers/typing.dart";
|
||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:ffi/ffi.dart";
|
||||
|
|
@ -63,6 +64,10 @@ class GomuksListenerController extends AsyncNotifier<void> {
|
|||
event.roomId: .new(events: .new({event.rowId: event})),
|
||||
}),
|
||||
);
|
||||
case "typing":
|
||||
ref
|
||||
.read(TypingController.provider.notifier)
|
||||
.set(.fromJson(decodedMuksEvent));
|
||||
case "events_decrypted":
|
||||
final decrypted = EventsDecrypted.fromJson(decodedMuksEvent);
|
||||
final metadata = ref
|
||||
|
|
@ -96,6 +101,7 @@ class GomuksListenerController extends AsyncNotifier<void> {
|
|||
ref.invalidate(roomProvider);
|
||||
ref.invalidate(accountDataProvider);
|
||||
ref.invalidate(invitesProvider);
|
||||
ref.invalidate(TypingController.provider);
|
||||
}
|
||||
|
||||
ref
|
||||
|
|
@ -153,6 +159,7 @@ class GomuksListenerController extends AsyncNotifier<void> {
|
|||
if (paused) {
|
||||
GomuksPauseSync(handle);
|
||||
} else {
|
||||
ref.invalidate(TypingController.provider);
|
||||
GomuksResumeSync(handle);
|
||||
}
|
||||
}, fireImmediately: true);
|
||||
|
|
|
|||
34
lib/controllers/room_typing.dart
Normal file
34
lib/controllers/room_typing.dart
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/settings.dart";
|
||||
import "package:nexus/controllers/typing.dart";
|
||||
|
||||
/// The other users typing in a room, or none if typing indicators are hidden
|
||||
/// in settings.
|
||||
class RoomTypingController(final String roomId)
|
||||
extends Notifier<IList<String>> {
|
||||
@override
|
||||
IList<String> build() {
|
||||
final shouldShow = ref.watch(
|
||||
SettingsController.provider.select(
|
||||
(settings) => settings.value?.typingIndicators != .neither,
|
||||
),
|
||||
);
|
||||
if (!shouldShow) return const .empty();
|
||||
|
||||
final userId = ref.watch(
|
||||
ClientStateController.provider.select((state) => state?.userId),
|
||||
);
|
||||
|
||||
return ref
|
||||
.watch(TypingController.provider.select((typing) => typing[roomId]))
|
||||
?.remove(userId ?? "") ??
|
||||
const .empty();
|
||||
}
|
||||
|
||||
static final provider = NotifierProvider.family
|
||||
.autoDispose<RoomTypingController, IList<String>, String>(
|
||||
RoomTypingController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import "package:nexus/helpers/extensions/distributor_name.dart";
|
|||
import "package:nexus/models/account_data.dart";
|
||||
import "package:nexus/models/room_order.dart";
|
||||
import "package:nexus/models/settings_category.dart";
|
||||
import "package:nexus/models/typing_indicators.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/widgets/settings/dialog_list_tile.dart";
|
||||
import "package:nexus/widgets/reset_encryption_sheet.dart";
|
||||
|
|
@ -183,6 +184,34 @@ class SettingsSectionsController
|
|||
),
|
||||
]),
|
||||
),
|
||||
.new(
|
||||
title: "Privacy",
|
||||
icon: Icons.privacy_tip,
|
||||
settings: .new([
|
||||
.new(
|
||||
title: "Typing Indicators",
|
||||
description: "Show when others are typing, and let others see when you're typing.",
|
||||
icon: Icons.keyboard,
|
||||
builder: (title, description, icon) =>
|
||||
DialogListTile<TypingIndicators>(
|
||||
icon: Icon(icon),
|
||||
title: title,
|
||||
subtitle: Text(description),
|
||||
value: settings.typingIndicators,
|
||||
options: TypingIndicators.values,
|
||||
getName: (option) => switch (option) {
|
||||
.showAndSend => "Show and send",
|
||||
.show => "Only show",
|
||||
.neither => "Neither",
|
||||
},
|
||||
onChanged: (value) => ref
|
||||
.read(SettingsController.provider.notifier)
|
||||
.set(settings.copyWith(typingIndicators: value))
|
||||
.onError(showError),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
if (ref.watch(ClientStateController.provider)?.isLoggedIn == true)
|
||||
"Account": .new([
|
||||
|
|
|
|||
15
lib/controllers/typing.dart
Normal file
15
lib/controllers/typing.dart
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/typing.dart";
|
||||
|
||||
class TypingController extends Notifier<IMap<String, IList<String>>> {
|
||||
@override
|
||||
IMap<String, IList<String>> build() => .new();
|
||||
|
||||
void set(Typing typing) => state = state.add(typing.roomId, typing.userIds);
|
||||
|
||||
static final provider =
|
||||
NotifierProvider<TypingController, IMap<String, IList<String>>>(
|
||||
TypingController.new,
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue