service: Implement setting the subscription state of a contact
This commit is contained in:
parent
b813f5e5e1
commit
dfecaba50e
@ -25,7 +25,7 @@ SharedMedium sharedMediumDbToModel(DBSharedMedium s) {
|
||||
);
|
||||
}
|
||||
|
||||
Conversation conversationDbToModel(DBConversation c, bool inRoster, String? subscription) {
|
||||
Conversation conversationDbToModel(DBConversation c, bool inRoster, String subscription) {
|
||||
final media = c.sharedMedia.map(sharedMediumDbToModel).toList();
|
||||
media.sort((a, b) => a.timestamp.compareTo(b.timestamp));
|
||||
|
||||
@ -50,6 +50,7 @@ RosterItem rosterDbToModel(DBRosterItem i) {
|
||||
avatarUrl: i.avatarUrl,
|
||||
jid: i.jid,
|
||||
subscription: i.subscription,
|
||||
ask: i.ask,
|
||||
groups: i.groups,
|
||||
title: i.title
|
||||
);
|
||||
@ -117,7 +118,7 @@ class DatabaseService {
|
||||
final conv = conversationDbToModel(
|
||||
c,
|
||||
rosterItem != null,
|
||||
rosterItem?.subscription
|
||||
rosterItem?.subscription ?? "none"
|
||||
);
|
||||
tmp.add(conv);
|
||||
_conversationCache[conv.id] = conv;
|
||||
@ -181,7 +182,7 @@ class DatabaseService {
|
||||
});
|
||||
|
||||
final rosterItem = await getRosterItemByJid(c.jid);
|
||||
final conversation = conversationDbToModel(c, rosterItem != null, rosterItem?.subscription);
|
||||
final conversation = conversationDbToModel(c, rosterItem != null, rosterItem?.subscription ?? "none");
|
||||
_conversationCache[c.id!] = conversation;
|
||||
return conversation;
|
||||
}
|
||||
@ -205,7 +206,7 @@ class DatabaseService {
|
||||
});
|
||||
|
||||
final rosterItem = await getRosterItemByJid(c.jid);
|
||||
final conversation = conversationDbToModel(c, rosterItem != null, rosterItem?.subscription);
|
||||
final conversation = conversationDbToModel(c, rosterItem != null, rosterItem?.subscription ?? "none");
|
||||
_conversationCache[c.id!] = conversation;
|
||||
|
||||
return conversation;
|
||||
@ -361,12 +362,13 @@ class DatabaseService {
|
||||
}
|
||||
|
||||
/// Create a roster item from data
|
||||
Future<RosterItem> addRosterItemFromData(String avatarUrl, String jid, String title, String subscription, { List<String>? groups }) async {
|
||||
Future<RosterItem> addRosterItemFromData(String avatarUrl, String jid, String title, String subscription, String ask, { List<String>? groups }) async {
|
||||
final rosterItem = DBRosterItem()
|
||||
..jid = jid
|
||||
..title = title
|
||||
..avatarUrl = avatarUrl
|
||||
..subscription = subscription
|
||||
..ask = ask
|
||||
..groups = groups ?? const [];
|
||||
|
||||
await isar.writeTxn((isar) async {
|
||||
@ -380,7 +382,7 @@ class DatabaseService {
|
||||
}
|
||||
|
||||
/// Updates the roster item with id [id] inside the database.
|
||||
Future<RosterItem> updateRosterItem({ required int id, String? avatarUrl, String? title, String? subscription, List<String>? groups }) async {
|
||||
Future<RosterItem> updateRosterItem({ required int id, String? avatarUrl, String? title, String? subscription, String? ask, List<String>? groups }) async {
|
||||
final i = (await isar.dBRosterItems.get(id))!;
|
||||
if (avatarUrl != null) {
|
||||
i.avatarUrl = avatarUrl;
|
||||
@ -394,6 +396,9 @@ class DatabaseService {
|
||||
if (subscription != null) {
|
||||
i.subscription = subscription;
|
||||
}
|
||||
if (ask != null) {
|
||||
i.ask = ask;
|
||||
}
|
||||
|
||||
await isar.writeTxn((isar) async {
|
||||
await isar.dBRosterItems.put(i);
|
||||
|
@ -16,4 +16,6 @@ class DBRosterItem {
|
||||
late List<String> groups;
|
||||
|
||||
late String subscription;
|
||||
|
||||
late String ask;
|
||||
}
|
||||
|
@ -270,11 +270,24 @@ Future<void> performSetAvatar(SetAvatarCommand command, { dynamic extra }) async
|
||||
}
|
||||
|
||||
Future<void> performSetShareOnlineStatus(SetShareOnlineStatusCommand command, { dynamic extra }) async {
|
||||
final xmpp = GetIt.I.get<XmppConnection>();
|
||||
final roster = GetIt.I.get<RosterService>();
|
||||
final db = GetIt.I.get<DatabaseService>();
|
||||
final item = await db.getRosterItemByJid(command.jid);
|
||||
|
||||
// TODO: Maybe log
|
||||
if (item == null) return;
|
||||
|
||||
if (command.share) {
|
||||
xmpp.getPresenceManager().sendSubscriptionRequestApproval(command.jid);
|
||||
if (item.ask == "subscribe") {
|
||||
roster.acceptSubscriptionRequest(command.jid);
|
||||
} else {
|
||||
roster.sendSubscriptionRequest(command.jid);
|
||||
}
|
||||
} else {
|
||||
xmpp.getPresenceManager().sendUnsubscriptionRequest(command.jid);
|
||||
if (item.ask == "subscribe") {
|
||||
roster.rejectSubscriptionRequest(command.jid);
|
||||
} else {
|
||||
roster.sendUnsubscriptionRequest(command.jid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ Future<RosterDiffEvent> rosterDiff(List<RosterItem> currentRoster, List<XmppRost
|
||||
item.jid,
|
||||
item.name ?? item.jid.split("@")[0],
|
||||
item.subscription,
|
||||
item.ask ?? "",
|
||||
groups: item.groups
|
||||
);
|
||||
|
||||
@ -102,6 +103,7 @@ Future<RosterDiffEvent> rosterDiff(List<RosterItem> currentRoster, List<XmppRost
|
||||
item.jid,
|
||||
item.jid.split("@")[0],
|
||||
item.subscription,
|
||||
item.ask ?? "",
|
||||
groups: item.groups
|
||||
));
|
||||
}
|
||||
@ -134,8 +136,13 @@ class RosterService {
|
||||
/// and, if it was successful, create the database entry. Returns the
|
||||
/// [RosterItem] model object.
|
||||
Future<RosterItem> addToRosterWrapper(String avatarUrl, String jid, String title) async {
|
||||
// TODO: Correct?
|
||||
final item = await GetIt.I.get<DatabaseService>().addRosterItemFromData(avatarUrl, jid, title, "to");
|
||||
final item = await GetIt.I.get<DatabaseService>().addRosterItemFromData(
|
||||
avatarUrl,
|
||||
jid,
|
||||
title,
|
||||
"none",
|
||||
""
|
||||
);
|
||||
final result = await GetIt.I.get<XmppConnection>().getRosterManager().addToRoster(jid, title);
|
||||
if (!result) {
|
||||
// TODO: Signal error?
|
||||
|
@ -23,7 +23,7 @@ class Conversation with _$Conversation {
|
||||
// Indicates, if [jid] is a regular user, if the user is in the roster.
|
||||
bool inRoster,
|
||||
// The subscription state of the roster item
|
||||
String? subscription
|
||||
String subscription
|
||||
) = _Conversation;
|
||||
|
||||
// JSON
|
||||
|
@ -6,16 +6,18 @@ class RosterItem extends Equatable {
|
||||
final String jid;
|
||||
final String title;
|
||||
final String subscription;
|
||||
final String ask;
|
||||
final List<String> groups;
|
||||
final int id;
|
||||
|
||||
const RosterItem({ required this.avatarUrl, required this.jid, required this.title, required this.subscription, required this.groups, required this.id });
|
||||
const RosterItem({ required this.avatarUrl, required this.jid, required this.title, required this.subscription, required this.groups, required this.ask, required this.id });
|
||||
|
||||
RosterItem.fromJson(Map<String, dynamic> json)
|
||||
: avatarUrl = json["avatarUrl"],
|
||||
jid = json["jid"],
|
||||
title = json["title"],
|
||||
subscription = json["subscription"],
|
||||
ask = json["ask"],
|
||||
groups = List<String>.from(json["groups"]!),
|
||||
id = json["id"];
|
||||
|
||||
@ -24,6 +26,7 @@ class RosterItem extends Equatable {
|
||||
"jid": jid,
|
||||
"title": title,
|
||||
"subscription": subscription,
|
||||
"ask": ask,
|
||||
"groups": groups,
|
||||
"id": id
|
||||
};
|
||||
@ -32,5 +35,5 @@ class RosterItem extends Equatable {
|
||||
bool get stringify => true;
|
||||
|
||||
@override
|
||||
List<Object> get props => [ avatarUrl, jid, title, subscription, id, groups ];
|
||||
List<Object> get props => [ avatarUrl, jid, title, subscription, id, groups, ask ];
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
||||
on<ProfilePageRequestedEvent>(_onProfileRequested);
|
||||
on<ConversationUpdatedEvent>(_onConversationUpdated);
|
||||
on<AvatarSetEvent>(_onAvatarSet);
|
||||
on<SetSubscriptionStateEvent>(_onSetSubscriptionState);
|
||||
}
|
||||
|
||||
Future<void> _onProfileRequested(ProfilePageRequestedEvent event, Emitter<ProfileState> emit) async {
|
||||
@ -71,4 +72,13 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
||||
awaitable: false
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onSetSubscriptionState(SetSubscriptionStateEvent event, Emitter<ProfileState> emit) async {
|
||||
// TODO: Maybe already emit the state change to have it instant and debounce it until
|
||||
// everything else is done
|
||||
GetIt.I.get<BackgroundServiceDataSender>().sendData(
|
||||
SetShareOnlineStatusCommand(jid: event.jid, share: event.shareStatus),
|
||||
awaitable: false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -35,3 +35,11 @@ class AvatarSetEvent extends ProfileEvent {
|
||||
|
||||
AvatarSetEvent(this.path, this.hash);
|
||||
}
|
||||
|
||||
/// Triggered by the UI when the subscription state should be set
|
||||
class SetSubscriptionStateEvent extends ProfileEvent {
|
||||
final String jid;
|
||||
final bool shareStatus;
|
||||
|
||||
SetSubscriptionStateEvent(this.jid, this.shareStatus);
|
||||
}
|
||||
|
@ -50,14 +50,13 @@ class ProfilePage extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32.0).add(EdgeInsets.only(top: 8.0)),
|
||||
child: SettingsTile.switchTile(
|
||||
title: "Share online status",
|
||||
// TODO: This
|
||||
// TODO: Requires that we also store the subscription state in the
|
||||
// database.
|
||||
switchValue: state.conversation!.subscription == "to" || state.conversation!.subscription == "both",
|
||||
onToggle: (value) {
|
||||
GetIt.I.get<BackgroundServiceDataSender>().sendData(
|
||||
SetShareOnlineStatusCommand(jid: state.conversation!.jid, share: value),
|
||||
awaitable: false
|
||||
context.read<ProfileBloc>().add(
|
||||
SetSubscriptionStateEvent(
|
||||
state.conversation!.jid,
|
||||
value
|
||||
)
|
||||
);
|
||||
}
|
||||
)
|
||||
|
@ -12,9 +12,10 @@ class XmppRosterItem {
|
||||
final String jid;
|
||||
final String? name;
|
||||
final String subscription;
|
||||
final String? ask;
|
||||
final List<String> groups;
|
||||
|
||||
XmppRosterItem({ required this.jid, required this.subscription, this.name, this.groups = const [] });
|
||||
XmppRosterItem({ required this.jid, required this.subscription, this.ask, this.name, this.groups = const [] });
|
||||
}
|
||||
|
||||
enum RosterRemovalResult {
|
||||
@ -100,6 +101,7 @@ class RosterManager extends XmppManagerBase {
|
||||
item: XmppRosterItem(
|
||||
jid: item.attributes["jid"]!,
|
||||
subscription: item.attributes["subscription"]!,
|
||||
ask: item.attributes["ask"],
|
||||
name: item.attributes["name"],
|
||||
),
|
||||
ver: query.attributes["ver"]
|
||||
@ -145,6 +147,7 @@ class RosterManager extends XmppManagerBase {
|
||||
name: item.attributes["name"],
|
||||
jid: item.attributes["jid"]!,
|
||||
subscription: item.attributes["subscription"]!,
|
||||
ask: item.attributes["ask"],
|
||||
groups: item.findTags("group").map((groupNode) => groupNode.innerText()).toList()
|
||||
)).toList();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user