Added a context menu entry for pinning/unpinning
; We can now also send the state event via the setState call.
This commit is contained in:
parent
5fef08b88e
commit
135be17555
6 changed files with 94 additions and 13 deletions
|
|
@ -94,9 +94,9 @@ A simple and user-friendly Matrix client made with Flutter and a Gomuks backend.
|
||||||
- [x] Editing
|
- [x] Editing
|
||||||
- [x] Deleting
|
- [x] Deleting
|
||||||
- [x] Reactions
|
- [x] Reactions
|
||||||
- [ ] Pins
|
- [x] Pins
|
||||||
- [ ] Displaying
|
- [x] Displaying
|
||||||
- [ ] Creating
|
- [x] Creating
|
||||||
- [ ] Threads
|
- [ ] Threads
|
||||||
- [x] Profile popouts
|
- [x] Profile popouts
|
||||||
- [x] Working actions
|
- [x] Working actions
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import "package:nexus/models/requests/report_request.dart";
|
||||||
import "package:nexus/models/requests/send_event_request.dart";
|
import "package:nexus/models/requests/send_event_request.dart";
|
||||||
import "package:nexus/models/requests/send_message_request.dart";
|
import "package:nexus/models/requests/send_message_request.dart";
|
||||||
import "package:nexus/models/requests/set_membership_request.dart";
|
import "package:nexus/models/requests/set_membership_request.dart";
|
||||||
|
import "package:nexus/models/requests/set_state_request.dart";
|
||||||
import "package:nexus/models/room.dart";
|
import "package:nexus/models/room.dart";
|
||||||
import "package:nexus/models/sync_data.dart";
|
import "package:nexus/models/sync_data.dart";
|
||||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||||
|
|
@ -172,6 +173,9 @@ class ClientController extends AsyncNotifier<int> {
|
||||||
Future<Event> sendEvent(SendEventRequest request) async =>
|
Future<Event> sendEvent(SendEventRequest request) async =>
|
||||||
Event.fromJson(await _sendCommand("send_event", request.toJson()));
|
Event.fromJson(await _sendCommand("send_event", request.toJson()));
|
||||||
|
|
||||||
|
Future<Event> setState(SetStateRequest request) async =>
|
||||||
|
Event.fromJson(await _sendCommand("set_state", request.toJson()));
|
||||||
|
|
||||||
Future<String?> verify(String recoveryKey) async {
|
Future<String?> verify(String recoveryKey) async {
|
||||||
try {
|
try {
|
||||||
await _sendCommand("verify", {"recovery_key": recoveryKey});
|
await _sendCommand("verify", {"recovery_key": recoveryKey});
|
||||||
|
|
|
||||||
|
|
@ -41,22 +41,49 @@ class PinnedEventsController extends AsyncNotifier<IList<Event>> {
|
||||||
return .new();
|
return .new();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> togglePin(Event event) async {
|
Future<void> addPin(Event event) async {
|
||||||
final client = ref.read(ClientController.provider.notifier);
|
final client = ref.read(ClientController.provider.notifier);
|
||||||
final current = await future;
|
final current = await future;
|
||||||
|
|
||||||
final updatedPinnedIds = current.any((e) => e.eventId == event.eventId)
|
if (current.any((ev) => ev.eventId == event.eventId)) {
|
||||||
? current
|
return;
|
||||||
.where((e) => e.eventId != event.eventId)
|
}
|
||||||
.map((e) => e.eventId)
|
|
||||||
.toList()
|
|
||||||
: [...current.map((e) => e.eventId), event.eventId];
|
|
||||||
|
|
||||||
await client.sendEvent(
|
final updatedPinnedIds = [
|
||||||
|
...current.map((ev) => ev.eventId),
|
||||||
|
event.eventId,
|
||||||
|
];
|
||||||
|
|
||||||
|
await client.setState(
|
||||||
.new(
|
.new(
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
type: EventType.pinnedEvents.type,
|
type: EventType.pinnedEvents.type,
|
||||||
stateKey: "",
|
stateKey:
|
||||||
|
"", //The empty string stands for m.room.pinned_events according to matrix spec.
|
||||||
|
content: {"pinned": updatedPinnedIds},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> removePin(Event event) async {
|
||||||
|
final client = ref.read(ClientController.provider.notifier);
|
||||||
|
final current = await future;
|
||||||
|
|
||||||
|
if (!current.any((ev) => ev.eventId == event.eventId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final updatedPinnedIds = [
|
||||||
|
...current
|
||||||
|
.where((ev) => ev.eventId != event.eventId)
|
||||||
|
.map((ev) => ev.eventId),
|
||||||
|
];
|
||||||
|
|
||||||
|
await client.setState(
|
||||||
|
.new(
|
||||||
|
roomId: roomId,
|
||||||
|
type: EventType.pinnedEvents.type,
|
||||||
|
stateKey: "", //The empty string stands for m.room.pinned_events according to matrix spec.
|
||||||
content: {"pinned": updatedPinnedIds},
|
content: {"pinned": updatedPinnedIds},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ abstract class SendEventRequest with _$SendEventRequest {
|
||||||
required String roomId,
|
required String roomId,
|
||||||
required String type,
|
required String type,
|
||||||
required Map<String, dynamic> content,
|
required Map<String, dynamic> content,
|
||||||
@Default(null) String? stateKey,
|
|
||||||
@Default(false) bool synchronous,
|
@Default(false) bool synchronous,
|
||||||
@Default(false) bool disableEncryption,
|
@Default(false) bool disableEncryption,
|
||||||
}) = _SendEventRequest;
|
}) = _SendEventRequest;
|
||||||
|
|
|
||||||
17
lib/models/requests/set_state_request.dart
Normal file
17
lib/models/requests/set_state_request.dart
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
part "set_state_request.freezed.dart";
|
||||||
|
part "set_state_request.g.dart";
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class SetStateRequest with _$SetStateRequest {
|
||||||
|
const factory SetStateRequest({
|
||||||
|
required String roomId,
|
||||||
|
required String type,
|
||||||
|
required String stateKey,
|
||||||
|
required Map<String, dynamic> content,
|
||||||
|
@Default(0) int delayMs,
|
||||||
|
}) = _SetStateRequest;
|
||||||
|
|
||||||
|
factory SetStateRequest.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$SetStateRequestFromJson(json);
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import "package:measure_size/measure_size.dart";
|
||||||
import "package:nexus/controllers/account_data_controller.dart";
|
import "package:nexus/controllers/account_data_controller.dart";
|
||||||
import "package:nexus/controllers/client_controller.dart";
|
import "package:nexus/controllers/client_controller.dart";
|
||||||
import "package:nexus/controllers/client_state_controller.dart";
|
import "package:nexus/controllers/client_state_controller.dart";
|
||||||
|
import "package:nexus/controllers/pinned_events_controller.dart";
|
||||||
import "package:nexus/controllers/power_level_controller.dart";
|
import "package:nexus/controllers/power_level_controller.dart";
|
||||||
import "package:nexus/controllers/rooms_controller.dart";
|
import "package:nexus/controllers/rooms_controller.dart";
|
||||||
import "package:nexus/controllers/room_chat_controller.dart";
|
import "package:nexus/controllers/room_chat_controller.dart";
|
||||||
|
|
@ -249,6 +250,39 @@ class RoomChat extends HookConsumerWidget {
|
||||||
},
|
},
|
||||||
child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")),
|
child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")),
|
||||||
),
|
),
|
||||||
|
if (ref.watch(
|
||||||
|
PowerLevelController.provider(
|
||||||
|
PowerLevelConfig(eventType: .pinnedEvents, roomId: roomId),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
() {
|
||||||
|
final isPinned = ref
|
||||||
|
.watch(PinnedEventsController.provider(roomId))
|
||||||
|
.maybeWhen(
|
||||||
|
data: (pinnedEvents) =>
|
||||||
|
pinnedEvents.any((ev) => ev.eventId == event.eventId),
|
||||||
|
orElse: () => false,
|
||||||
|
);
|
||||||
|
|
||||||
|
return PopupMenuItem(
|
||||||
|
onTap: () async {
|
||||||
|
final notifier = ref.read(
|
||||||
|
PinnedEventsController.provider(roomId).notifier,
|
||||||
|
);
|
||||||
|
if (isPinned) {
|
||||||
|
await notifier.removePin(event);
|
||||||
|
} else {
|
||||||
|
await notifier.addPin(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
isPinned ? Icons.push_pin_outlined : Icons.push_pin,
|
||||||
|
),
|
||||||
|
title: Text(isPinned ? "Unpin Event" : "Pin Event"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}(),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final room = ref.watch(
|
final room = ref.watch(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue