- #57 Implemented XEP-0172 User Nickname

- Added New Column 'nickname' in roster_items Table
- DB version changed from 13 to 14
This commit is contained in:
Mehrooz Khan 2021-08-26 13:04:05 +05:00 committed by Matthew Wild
parent d10c7842d3
commit c26d44cd96
11 changed files with 247 additions and 67 deletions

View file

@ -24,7 +24,7 @@ import TigaseSwift
public class DBSchemaManager {
static let CURRENT_VERSION = 13;
static let CURRENT_VERSION = 14;
fileprivate let dbConnection: DBConnection;

7
Shared/db-schema-14.sql Normal file
View file

@ -0,0 +1,7 @@
BEGIN;
ALTER TABLE roster_items ADD COLUMN nickname TEXT;
COMMIT;
PRAGMA user_version = 14;

View file

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
E928AD4326D6A08A00F29F93 /* db-schema-14.sql in Resources */ = {isa = PBXBuildFile; fileRef = E928AD4226D6A08A00F29F93 /* db-schema-14.sql */; };
E95AA70226D38B6F00A38D44 /* DisplayNameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95AA70126D38B6E00A38D44 /* DisplayNameViewController.swift */; };
E963721026D786D000332482 /* BlockingCommandModuleExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E963720F26D786D000332482 /* BlockingCommandModuleExtension.swift */; };
E963721226D79D3A00332482 /* PrivacyPolicyTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E963721126D79D3A00332482 /* PrivacyPolicyTableViewCell.swift */; };
@ -14,6 +15,7 @@
E9D384B426CA95FF009BEAF3 /* UIDeviceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D384B326CA95FF009BEAF3 /* UIDeviceExtension.swift */; };
E9D384B626CBB606009BEAF3 /* CustomUISlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D384B526CBB606009BEAF3 /* CustomUISlider.swift */; };
E9D384B826CBBEB6009BEAF3 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9D384B726CBBEB6009BEAF3 /* Extensions.swift */; };
E9EC2B3326D554C000222BB9 /* PEPDisplayNameModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9EC2B3226D554C000222BB9 /* PEPDisplayNameModule.swift */; };
FE00157D2017617B00490340 /* StreamFeaturesCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE00157C2017617B00490340 /* StreamFeaturesCache.swift */; };
FE00157F2019090300490340 /* ExperimentalSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE00157E2019090300490340 /* ExperimentalSettingsViewController.swift */; };
FE01ADA91E224CF400FA7E65 /* SiskinPushNotificationsModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE01ADA81E224CF400FA7E65 /* SiskinPushNotificationsModule.swift */; };
@ -291,6 +293,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
E928AD4226D6A08A00F29F93 /* db-schema-14.sql */ = {isa = PBXFileReference; lastKnownFileType = text; path = "db-schema-14.sql"; sourceTree = "<group>"; };
E95AA70126D38B6E00A38D44 /* DisplayNameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayNameViewController.swift; sourceTree = "<group>"; };
E963720F26D786D000332482 /* BlockingCommandModuleExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockingCommandModuleExtension.swift; sourceTree = "<group>"; };
E963721126D79D3A00332482 /* PrivacyPolicyTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyTableViewCell.swift; sourceTree = "<group>"; };
@ -298,6 +301,7 @@
E9D384B326CA95FF009BEAF3 /* UIDeviceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDeviceExtension.swift; sourceTree = "<group>"; };
E9D384B526CBB606009BEAF3 /* CustomUISlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomUISlider.swift; sourceTree = "<group>"; };
E9D384B726CBBEB6009BEAF3 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
E9EC2B3226D554C000222BB9 /* PEPDisplayNameModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PEPDisplayNameModule.swift; sourceTree = "<group>"; };
FE00157C2017617B00490340 /* StreamFeaturesCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamFeaturesCache.swift; sourceTree = "<group>"; };
FE00157E2019090300490340 /* ExperimentalSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperimentalSettingsViewController.swift; sourceTree = "<group>"; };
FE01ADA81E224CF400FA7E65 /* SiskinPushNotificationsModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SiskinPushNotificationsModule.swift; sourceTree = "<group>"; };
@ -794,6 +798,7 @@
FEC79198241BE89E007BE572 /* db-schema-11.sql */,
FE3BA0BF24B61583000C80D4 /* db-schema-12.sql */,
FEBC12F124C70DE000689475 /* db-schema-13.sql */,
E928AD4226D6A08A00F29F93 /* db-schema-14.sql */,
);
path = Shared;
sourceTree = "<group>";
@ -906,6 +911,7 @@
FE75A00E2375F324001E78D9 /* PushEventHandler.swift */,
FEDC6789238A9F16005C0FAB /* BlockedEventHandler.swift */,
FE3E3879242765E700D3A8E8 /* MixEventHandler.swift */,
E9EC2B3226D554C000222BB9 /* PEPDisplayNameModule.swift */,
E963720F26D786D000332482 /* BlockingCommandModuleExtension.swift */,
);
path = service;
@ -1179,6 +1185,7 @@
FECEF29823B7B838007EC323 /* db-schema-9.sql in Resources */,
FE3BA0C024B61583000C80D4 /* db-schema-12.sql in Resources */,
FE759FF02371F21C001E78D9 /* db-schema-4.sql in Resources */,
E928AD4326D6A08A00F29F93 /* db-schema-14.sql in Resources */,
FE759FF32371F21C001E78D9 /* db-schema-7.sql in Resources */,
FE759FF12371F21C001E78D9 /* db-schema-5.sql in Resources */,
FE759FF523741527001E78D9 /* db-schema-8.sql in Resources */,
@ -1302,6 +1309,7 @@
FE3A45CF1CE49D3300C36264 /* RosterItemEditViewController.swift in Sources */,
FEE49DD7242688E100900BBB /* ChannelViewController.swift in Sources */,
FE507A211CDB7B3B001A015C /* SettingsViewController.swift in Sources */,
E9EC2B3326D554C000222BB9 /* PEPDisplayNameModule.swift in Sources */,
FE507A191CDB7B3B001A015C /* DBChatHistoryStore.swift in Sources */,
FEA8D65D1F2F6AF60077C12F /* VCardEntryTypeAwareTableViewCell.swift in Sources */,
FEBC12F524C70E7F00689475 /* DBChatHistorySyncStore.swift in Sources */,

View file

@ -509,11 +509,7 @@ class ChatTitleView: UIView {
func reload(for account: BareJID, with jid: BareJID) {
if let rosterModule: RosterModule = XmppService.instance.getClient(for: account)?.modulesManager.getModule(RosterModule.ID) {
self.name = rosterModule.rosterStore.get(for: JID(jid))?.name ?? jid.stringValue;
} else {
self.name = jid.stringValue;
}
self.name = PEPDisplayNameModule.getDisplayName(account: account, for: jid)
self.encryption = (DBChatStore.instance.getChat(for: account, with: jid) as? DBChat)?.options.encryption;
}

View file

@ -118,10 +118,8 @@ class ChatsListViewController: UITableViewController {
cell.nameLabel.text = channel.name ?? item.jid.localPart ?? item.jid.stringValue;
cell.avatarStatusView.setStatus(channel.state == .joined ? Presence.Show.online : nil)
default:
let rosterModule: RosterModule? = xmppClient?.modulesManager.getModule(RosterModule.ID);
let rosterItem = rosterModule?.rosterStore.get(for: item.jid);
let name = rosterItem?.name ?? item.jid.bareJid.stringValue;
cell.nameLabel.text = name;
let name = PEPDisplayNameModule.getDisplayName(account: item.account, for: BareJID(item.jid))
cell.nameLabel.text = name
cell.avatarStatusView.set(name: name, avatar: AvatarManager.instance.avatar(for: item.jid.bareJid, on: item.account), orDefault: AvatarManager.instance.defaultAvatar);
let presenceModule: PresenceModule? = xmppClient?.modulesManager.getModule(PresenceModule.ID);
let presence = presenceModule?.presenceStore.getBestPresence(for: item.jid.bareJid);
@ -471,6 +469,7 @@ class ChatsListViewController: UITableViewController {
NotificationCenter.default.addObserver(self, selector: #selector(chatOpened), name: DBChatStore.CHAT_OPENED, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(chatClosed), name: DBChatStore.CHAT_CLOSED, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(chatUpdated), name: DBChatStore.CHAT_UPDATED, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(nickChanged(_:)), name: NickChangeEventHandler.NICK_CHANGED, object: nil)
applyActionsQueue.async {
DispatchQueue.main.sync {
@ -499,6 +498,11 @@ class ChatsListViewController: UITableViewController {
self.refreshItem(for: account, with: jid);
}
@objc func nickChanged(_ notification: Notification) {
guard let account = notification.userInfo?["account"] as? BareJID, let jid = notification.userInfo?["jid"] as? BareJID else { return }
self.refreshItem(for: account, with: jid)
}
@objc func chatOpened(_ notification: Notification) {
guard let opened = notification.object as? DBChatProtocol else {
return;
@ -563,26 +567,6 @@ class ChatsListViewController: UITableViewController {
print("XX: executing for", actions.count, "actions");
var store = DispatchQueue.main.sync { return self.store };
// let removeIndexes = store.indexes(for: actions.filter { (item) -> Bool in
// item.action == .remove;
// });
// let refreshActions = actions.filter { (item) -> Bool in
// item.action == .refresh;
// };
// let refreshIndexes = store.indexes(for: refreshActions);
//
// store.remove(for: removeIndexes);
//
// let addActions = actions.filter { (item) -> Bool in
// return item.action == .add;
// }
//
// addActions.forEach { (item) in
// _ = store.add(for: item)
// }
//
// let addIndexes = store.indexes(for: addActions + refreshActions);
let removeIndexes = store.indexes(for: actions);

View file

@ -120,6 +120,9 @@ open class DBRosterStore: RosterCacheProvider {
fileprivate let insertItemGroupStmt: DBStatement;
fileprivate let deleteItemGroupsStmt: DBStatement;
fileprivate let updateNicknameStmt: DBStatement
fileprivate let getNicknameStmt: DBStatement
public init() {
self.dispatcher = QueueDispatcher(label: "db_roster_store");
@ -135,9 +138,28 @@ open class DBRosterStore: RosterCacheProvider {
insertItemGroupStmt = try! DBConnection.main.prepareStatement("INSERT INTO roster_items_groups (item_id, group_id) VALUES (:item_id, :group_id)");
deleteItemGroupsStmt = try! DBConnection.main.prepareStatement("DELETE FROM roster_items_groups WHERE item_id = :item_id");
updateNicknameStmt = try! DBConnection.main.prepareStatement("UPDATE roster_items SET nickname = :nickname WHERE jid = :jid")
getNicknameStmt = try! DBConnection.main.prepareStatement("SELECT nickname FROM roster_items WHERE jid = :jid")
NotificationCenter.default.addObserver(self, selector: #selector(DBRosterStore.accountRemoved), name: NSNotification.Name(rawValue: "accountRemoved"), object: nil);
}
func updateNick(jid: String, nick: String) {
dispatcher.sync {
let params: [String: Any?] = ["jid": jid, "nickname": nick]
_ = try! self.updateNicknameStmt.update(params)
}
}
func getNickname(jid: String) -> String? {
dispatcher.sync {
let params: [String: Any?] = ["jid":jid]
return try! getNicknameStmt.queryFirstMatching(params) { cursor in
return cursor["nickname"] as String?
}
}
}
func getAll(for account: BareJID) -> [DBRosterItem] {
return dispatcher.sync {
let params: [String: Any?] = ["account": account];

View file

@ -39,26 +39,23 @@ class RosterItemEditViewController: UITableViewController, UIPickerViewDataSourc
override func viewDidLoad() {
xmppService = (UIApplication.shared.delegate as! AppDelegate).xmppService;
super.viewDidLoad()
// Do any additional setup after loading the view
let accountPicker = UIPickerView();
accountPicker.dataSource = self;
accountPicker.delegate = self;
self.accountTextField.inputView = accountPicker;
// self.accountTextField.addTarget(self, action: #selector(RosterItemEditViewController.textFieldDidChange), for: UIControlEvents.editingChanged);
// self.jidTextField.addTarget(self, action: #selector(RosterItemEditViewController.textFieldDidChange), for: UIControlEvents.editingChanged);
self.jidTextField.text = jid?.stringValue;
self.accountTextField.text = account?.stringValue;
self.sendPresenceUpdatesSwitch.isOn = true;
self.receivePresenceUpdatesSwitch.isOn = true;//Settings.AutoSubscribeOnAcceptedSubscriptionRequest.getBool();
if account != nil && jid != nil {
self.receivePresenceUpdatesSwitch.isOn = true //Settings.AutoSubscribeOnAcceptedSubscriptionRequest.getBool();
if let account = account, let jid = jid {
self.jidTextField.isEnabled = false;
self.accountTextField.isEnabled = false;
if let sessionObject = xmppService.getClient(forJid: account!)?.sessionObject {
if let sessionObject = xmppService.getClient(forJid: account)?.sessionObject {
let rosterStore: RosterStore = RosterModule.getRosterStore(sessionObject)
if let rosterItem = rosterStore.get(for: jid!) {
self.nameTextField.text = rosterItem.name;
if let rosterItem = rosterStore.get(for: jid) {
self.nameTextField.text = PEPDisplayNameModule.getDisplayName(account: account, for: BareJID(jid))
self.sendPresenceUpdatesSwitch.isOn = rosterItem.subscription.isFrom;
self.receivePresenceUpdatesSwitch.isOn = rosterItem.subscription.isTo;
}
@ -77,18 +74,6 @@ class RosterItemEditViewController: UITableViewController, UIPickerViewDataSourc
// Dispose of any resources that can be recreated.
}
// func textFieldDidChange(_ textField: UITextField) {
// if textField.text?.isEmpty != false {
// textField.superview?.backgroundColor = UIColor.red;
//// textField.layer.borderColor = UIColor.red.cgColor;
//// textField.layer.borderWidth = 1;
// } else {
//// textField.layer.borderColor = UIColor(white: 1, alpha: 1).cgColor;
//// textField.layer.borderWidth = 0;
// textField.superview?.backgroundColor = UIColor.white;
// }
// }
@IBAction func saveBtnClicked(_ sender: UIBarButtonItem) {
saveChanges()
}
@ -196,15 +181,6 @@ class RosterItemEditViewController: UITableViewController, UIPickerViewDataSourc
}
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1;

View file

@ -46,6 +46,7 @@ class RosterViewController: AbstractRosterViewController, UIGestureRecognizerDel
updateNavBarColors();
NotificationCenter.default.addObserver(self, selector: #selector(settingsChanged(_:)), name: Settings.SETTINGS_CHANGED, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(self.nickChanged(_:)), name: NickChangeEventHandler.NICK_CHANGED, object: nil)
}
override func viewWillAppear(_ animated: Bool) {
@ -111,6 +112,19 @@ class RosterViewController: AbstractRosterViewController, UIGestureRecognizerDel
}
}
@objc func nickChanged(_ notification: Notification) {
guard let account = notification.userInfo?["account"] as? BareJID, let jid = notification.userInfo?["jid"] as? BareJID else { return }
if let sessionObject = XmppService.instance.getClient(forJid: account)?.sessionObject {
let rosterStore: RosterStore = RosterModule.getRosterStore(sessionObject)
if let rosterItem = rosterStore.get(for: JID(jid)), rosterItem.name == nil {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
override func initializeRosterProvider(availableOnly: Bool, sortOrder: RosterSortingOrder) {
let order = RosterSortingOrder(rawValue: Settings.RosterItemsOrder.getString() ?? "") ?? .alphabetical;
super.initializeRosterProvider(availableOnly: false, sortOrder: order);
@ -128,7 +142,7 @@ class RosterViewController: AbstractRosterViewController, UIGestureRecognizerDel
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! RosterItemTableViewCell;
if let item = roster?.item(at: indexPath) {
cell.nameLabel.text = item.displayName;
cell.nameLabel.text = PEPDisplayNameModule.getDisplayName(account: item.account, for: BareJID(item.jid))
cell.statusLabel.text = item.presence?.status ?? item.jid.stringValue;
cell.avatarStatusView.setStatus(item.presence?.show);
cell.avatarStatusView.set(name: item.displayName, avatar: AvatarManager.instance.avatar(for: item.jid.bareJid, on: item.account), orDefault: AvatarManager.instance.defaultAvatar);

View file

@ -0,0 +1,152 @@
//
// PEPDisplayNameModule.swift
// Snikket
//
// Created by Khalid Khan on 8/24/21.
// Copyright © 2021 Snikket. All rights reserved.
//
import Foundation
import TigaseSwift
class PEPDisplayNameModule: AbstractPEPModule {
public static let ID = "NICKNAME"
public static let XMLNS = "http://jabber.org/protocol/nick"
public static let PUBSUB_XMLNS = "http://jabber.org/protocol/pubsub";
public static let PUBSUB_EVENT_XMLNS = PUBSUB_XMLNS + "#event";
public static let FEATURES: [String] = [XMLNS + "+notify"]
var id = ID
var criteria = Criteria.name("message").add(Criteria.name("event", xmlns: PUBSUB_EVENT_XMLNS));
var features: [String] = FEATURES
func process(stanza: Stanza) throws {
throw ErrorCondition.bad_request
}
var context: Context!{
didSet {
if oldValue != nil {
oldValue.eventBus.unregister(handler: self, for: PubSubModule.NotificationReceivedEvent.TYPE);
}
if context != nil {
context.eventBus.register(handler: self, for: PubSubModule.NotificationReceivedEvent.TYPE);
}
}
}
func publishNick(nick: String, userJID: JID, completion: @escaping (Bool)->Void) {
guard let pubsubModule: PubSubModule = context.modulesManager.getModule(PubSubModule.ID) else {
print("Required PubSubModule is not registered!")
return
}
let payload = Element(name: "nick", cdata: nick, xmlns: PEPDisplayNameModule.XMLNS)
pubsubModule.publishItem(at: nil, to: PEPDisplayNameModule.XMLNS, payload: payload) { responseStanza in
switch responseStanza {
case .success(response: _, node: _, itemId: _):
completion(true)
case .failure(errorCondition: _, pubSubErrorCondition: _, response: _):
completion(false)
}
}
}
func retrieveNick(from jid: BareJID, itemId: String? = nil, completion: @escaping (String?)->Void) {
guard let pubsubModule: PubSubModule = context.modulesManager.getModule(PubSubModule.ID) else {
print("Required PubSubModule is not registered!")
return
}
pubsubModule.retrieveItems(from: jid, for: PEPDisplayNameModule.XMLNS) { responseStanza in
switch responseStanza {
case .success(_, _, let items,_):
if let nick = items.first?.payload?.value {
completion(nick)
} else { completion(nil) }
case .failure(errorCondition: _, pubsubErrorCondition: _, response: _):
completion(nil)
}
}
}
func handle(event: Event) {
switch event {
case let nre as PubSubModule.NotificationReceivedEvent:
guard nre.nodeName == PEPDisplayNameModule.XMLNS, let from = nre.message.from else { return }
let nick = nre.payload?.value
context.eventBus.fire(NickChangedEvent(sessionObject: nre.sessionObject, jid: from, itemId: nre.itemId, nick: nick))
default:
break;
}
}
static func getDisplayName(account: BareJID, for jid: BareJID) -> String {
guard let client = XmppService.instance.getClient(forJid: account) else { return "" }
let rosterModule: RosterModule? = client.modulesManager.getModule(RosterModule.ID);
let rosterItem = rosterModule?.rosterStore.get(for: JID(jid))
var name = rosterItem?.name ?? DBRosterStore.instance.getNickname(jid: jid.stringValue)
name = name == nil ? jid.localPart : name
return name ?? ""
}
public init() { }
class NickChangedEvent: Event {
public static let TYPE = NickChangedEvent()
public let type = "PEPNickChanged"
public let sessionObject: SessionObject!
public let jid: JID!
public let itemId: String?
public let nick: String?
init() {
self.sessionObject = nil
self.jid = nil
self.itemId = nil
self.nick = nil
}
init(sessionObject: SessionObject, jid: JID, itemId: String?, nick: String?) {
self.sessionObject = sessionObject
self.jid = jid
self.itemId = itemId
self.nick = nick ?? ""
}
}
}
class NickChangeEventHandler: XmppServiceEventHandler {
public static let NICK_CHANGED = Notification.Name("NICK_CHANGED")
var events: [Event] = [PEPDisplayNameModule.NickChangedEvent.TYPE]
func handle(event: Event) {
guard let event = event as? PEPDisplayNameModule.NickChangedEvent, let account = event.sessionObject.userBareJid, let jid = event.jid, let nick = event.nick else { return }
DBRosterStore.instance.updateNick(jid: jid.stringValue, nick: nick)
NotificationCenter.default.post(name: NickChangeEventHandler.NICK_CHANGED, object: self, userInfo: ["account":account, "jid": BareJID(jid)])
// if let nickname = DBRosterStore.instance.getNickname(jid: jid.stringValue), nickname != nick, let account = event.sessionObject.userBareJid {
// NotificationCenter.default.post(name: NickChangeEventHandler.NICK_CHANGED, object: self, userInfo: ["account":account,"jid": BareJID(jid)])
// }
}
}

View file

@ -49,9 +49,9 @@ open class XmppService: Logger, EventHandler {
fileprivate var fetchStart = NSDate();
#if targetEnvironment(simulator)
fileprivate let eventHandlers: [XmppServiceEventHandler] = [NewFeaturesDetector(), MessageEventHandler(), MucEventHandler.instance, PresenceRosterEventHandler(), AvatarEventHandler(), DiscoEventHandler(), PushEventHandler.instance, BlockedEventHandler.instance, MixEventHandler.instance];
fileprivate let eventHandlers: [XmppServiceEventHandler] = [NewFeaturesDetector(), MessageEventHandler(), MucEventHandler.instance, PresenceRosterEventHandler(), AvatarEventHandler(), NickChangeEventHandler(), DiscoEventHandler(), PushEventHandler.instance, BlockedEventHandler.instance, MixEventHandler.instance];
#else
fileprivate let eventHandlers: [XmppServiceEventHandler] = [NewFeaturesDetector(), MessageEventHandler(), MucEventHandler.instance, PresenceRosterEventHandler(), AvatarEventHandler(), DiscoEventHandler(), PushEventHandler.instance, JingleManager.instance, BlockedEventHandler.instance, MixEventHandler.instance];
fileprivate let eventHandlers: [XmppServiceEventHandler] = [NewFeaturesDetector(), MessageEventHandler(), MucEventHandler.instance, PresenceRosterEventHandler(), AvatarEventHandler(), NickChangeEventHandler(), DiscoEventHandler(), PushEventHandler.instance, JingleManager.instance, BlockedEventHandler.instance, MixEventHandler.instance];
#endif
public let dbCapsCache: DBCapabilitiesCache;
@ -666,6 +666,7 @@ open class XmppService: Logger, EventHandler {
_ = client.modulesManager.register(PubSubModule());
_ = client.modulesManager.register(PEPUserAvatarModule());
_ = client.modulesManager.register(PEPBookmarksModule());
_ = client.modulesManager.register(PEPDisplayNameModule())
let rosterModule = client.modulesManager.register(RosterModule());
let rosterStore = DBRosterStoreWrapper(sessionObject: client.sessionObject);
rosterStore.initialize();

View file

@ -47,9 +47,20 @@ class DisplayNameViewController: UIViewController {
@objc func done() {
if !textView.text.isEmpty, let account = account {
AccountSettings.displayName(account).set(string: textView.text)
let nick = textView.text ?? ""
if let pepModule: PEPDisplayNameModule = XmppService.instance.getClient(for: account)?.modulesManager.getModule(PEPDisplayNameModule.ID) {
pepModule.publishNick(nick: nick, userJID: JID(account), completion: { success in
AccountSettings.displayName(account).set(string: nick)
DispatchQueue.main.async {
self.navigationController?.popViewController(animated: true)
}
})
}
}
self.navigationController?.popViewController(animated: true)
}
}
@ -69,8 +80,17 @@ extension DisplayNameViewController: UITextViewDelegate {
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n", !textView.text.isEmpty, let account = account {
AccountSettings.displayName(account).set(string: textView.text)
self.navigationController?.popViewController(animated: true)
if let pepModule: PEPDisplayNameModule = XmppService.instance.getClient(for: account)?.modulesManager.getModule(PEPDisplayNameModule.ID) {
pepModule.publishNick(nick: textView.text ?? "", userJID: JID(account), completion: { success in
AccountSettings.displayName(account).set(string: textView.text)
DispatchQueue.main.async {
self.navigationController?.popViewController(animated: true)
}
})
}
textView.resignFirstResponder()
return false
}