private static void handleRequestAdd(byte[] id, byte[] sender_wallet, byte[] pub_key) { if (!(new Address(pub_key)).address.SequenceEqual(sender_wallet)) { Logging.error("Received invalid pubkey in handleRequestAdd for {0}", Base58Check.Base58CheckEncoding.EncodePlain(sender_wallet)); return; } Friend new_friend = FriendList.addFriend(sender_wallet, pub_key, Base58Check.Base58CheckEncoding.EncodePlain(sender_wallet), null, null, 0, false); if (new_friend != null) { new_friend.handshakeStatus = 1; FriendList.addMessageWithType(id, FriendMessageType.requestAdd, sender_wallet, ""); requestNickname(new_friend); } else { Friend friend = FriendList.getFriend(sender_wallet); friend.handshakeStatus = 1; if (friend.approved) { sendAcceptAdd(friend); } } }
private void onNetworkData(string data) { foreach (byte[] address in userAddresses) { Friend f = FriendList.getFriend(address); if (f != null) { SpixiMessage spixi_msg = new SpixiMessage(); spixi_msg.type = SpixiMessageCode.appData; spixi_msg.data = (new SpixiAppData(sessionId, UTF8Encoding.UTF8.GetBytes(data))).getBytes(); StreamMessage msg = new StreamMessage(); msg.type = StreamMessageCode.data; msg.recipient = f.walletAddress; msg.sender = Node.walletStorage.getPrimaryAddress(); msg.transaction = new byte[1]; msg.sigdata = new byte[1]; msg.data = spixi_msg.getBytes(); StreamProcessor.sendMessage(f, msg, false, false, false); } else { Logging.error("Friend {0} does not exist in the friend list.", Base58Check.Base58CheckEncoding.EncodePlain(address)); } } }
public void onRequest(byte[] recipient_address) { try { if (Address.validateChecksum(recipient_address) == false) { displaySpixiAlert("Invalid checksum", "Please make sure you typed the address correctly.", "OK"); return; } if (recipient_address.SequenceEqual(Node.walletStorage.getPrimaryAddress())) { displaySpixiAlert("Cannot add yourself", "The address you have entered is your own address.", "OK"); return; } if (FriendList.getFriend(recipient_address) != null) { displaySpixiAlert("Already exists", "This contact is already in your contacts list.", "OK"); return; } Friend friend = FriendList.addFriend(recipient_address, null, Base58Check.Base58CheckEncoding.EncodePlain(recipient_address), null, null, 0); FriendList.saveToStorage(); StreamProcessor.sendContactRequest(friend); }catch (Exception) { } Navigation.PopAsync(Config.defaultXamarinAnimations); }
private static void handleAcceptAdd(byte[] sender_wallet, byte[] aes_key) { // Retrieve the corresponding contact Friend friend = FriendList.getFriend(sender_wallet); if (friend == null) { byte[] pub_k = FriendList.findContactPubkey(sender_wallet); if (pub_k == null) { Console.WriteLine("Contact {0} not found in presence list!", Base58Check.Base58CheckEncoding.EncodePlain(sender_wallet)); return; } friend = FriendList.addFriend(sender_wallet, pub_k, Base58Check.Base58CheckEncoding.EncodePlain(sender_wallet), aes_key, null, 0); } else { friend.aesKey = aes_key; } friend.handshakeStatus = 2; friend.generateKeys(); friend.sendKeys(2); requestNickname(friend); sendNickname(friend); FriendList.addMessage(null, friend.walletAddress, friend.nickname + " has accepted your friend request."); }
public void displayAppRequests() { if (_webView == null) { return; } Utils.sendUiCommand(_webView, "clearAppRequests"); var app_pages = Node.customAppManager.getAppPages(); lock (app_pages) { foreach (CustomAppPage page in app_pages.Values) { if (page.accepted) { continue; } Friend f = FriendList.getFriend(page.hostUserAddress); CustomApp app = Node.customAppManager.getApp(page.appId); string text = f.nickname + " wants to use " + app.name + " with you."; Utils.sendUiCommand(_webView, "addAppRequest", Crypto.hashToString(page.sessionId), text); } if (VoIPManager.isInitiated() && !VoIPManager.currentCallAccepted) { Friend f = VoIPManager.currentCallContact; string text = f.nickname + " is calling you."; Utils.sendUiCommand(_webView, "addAppRequest", Crypto.hashToString(VoIPManager.currentCallSessionId), text); } } }
private void onRequest(string recipient, string amount) { byte[] recipient_bytes = Base58Check.Base58CheckEncoding.DecodePlain(recipient); Friend friend = FriendList.getFriend(recipient_bytes); if (friend != null && (new IxiNumber(amount)) > 0) { FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.requestFunds, friend.walletAddress, amount, true); SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.requestFunds, Encoding.UTF8.GetBytes(amount)); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.info; message.recipient = Base58Check.Base58CheckEncoding.DecodePlain(recipient); message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); message.id = friend_message.id; StreamProcessor.sendMessage(friend, message); Navigation.PopAsync(Config.defaultXamarinAnimations); }// else error? }
public static void handleRequestFileData(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { Logging.info("Received request file data"); try { using (MemoryStream m = new MemoryStream(data.data)) { using (BinaryReader reader = new BinaryReader(m)) { string uid = reader.ReadString(); ulong packet_number = reader.ReadUInt64(); TransferManager.sendFileData(friend, uid, packet_number); } } } catch (Exception e) { Logging.error("Exception occured while handling request file data from bytes: " + e); } } else { Logging.error("Received request file data from an unknown friend."); } }
// Called when accepting a file public static void handleAcceptFile(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { Logging.info("Received accept file"); try { using (MemoryStream m = new MemoryStream(data.data)) { using (BinaryReader reader = new BinaryReader(m)) { string uid = reader.ReadString(); TransferManager.receiveAcceptFile(friend, uid); } } } catch (Exception e) { Logging.error("Exception occured while handling accept file from bytes: " + e); } } else { Logging.error("Received accept file from an unknown friend."); } }
public void onChat(string friend_address, WebNavigatingEventArgs e) { byte[] id_bytes = Base58Check.Base58CheckEncoding.DecodePlain(friend_address); Friend friend = FriendList.getFriend(id_bytes); if (friend == null) { if (e != null) { e.Cancel = true; } return; } bool animated = Config.defaultXamarinAnimations; if (e == null) { animated = false; } Device.BeginInvokeOnMainThread(async() => { if (Navigation.NavigationStack.Count > 1) { await Navigation.PopToRootAsync(false); } await Navigation.PushAsync(new SingleChatPage(friend), animated); }); }
// Retrieve the transaction from local cache storage private void checkTransaction() { string confirmed_text = "CONFIRMED"; Transaction ctransaction = TransactionCache.getTransaction(transaction.id); if (ctransaction == null || ctransaction.applied == 0) { requestTransactionData(); ctransaction = transaction; confirmed_text = "UNCONFIRMED"; } IxiNumber amount = ctransaction.amount; string addresses = ""; byte[] addr = new Address(ctransaction.pubKey).address; if (addr.SequenceEqual(Node.walletStorage.getPrimaryAddress())) { // this is a sent payment foreach (var entry in ctransaction.toList) { Friend friend = FriendList.getFriend(entry.Key); if (friend != null) { addresses += friend.nickname + ": " + entry.Value.ToString() + "|"; } else { addresses += Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString() + "|"; } } } else { // this is a received payment amount = 0; Utils.sendUiCommand(webView, "setReceivedMode"); foreach (var entry in ctransaction.toList) { if (entry.Key.SequenceEqual(Node.walletStorage.getPrimaryAddress())) { addresses += Base58Check.Base58CheckEncoding.EncodePlain(entry.Key) + ": " + entry.Value.ToString() + "|"; amount += entry.Value; } } } // Convert unix timestamp string time = Utils.UnixTimeStampToString(Convert.ToDouble(ctransaction.timeStamp)); Utils.sendUiCommand(webView, "setData", amount.ToString(), ctransaction.fee.ToString(), addresses, time, confirmed_text, (ctransaction.fee / amount).ToString() + "%"); return; }
public void processQRResult(string result) { if (result.Contains(":ixi")) { string[] split = result.Split(new string[] { ":ixi" }, StringSplitOptions.None); if (split.Count() < 1) { return; } string wallet_to_send = split[0]; string nickname = wallet_to_send; Friend friend = FriendList.getFriend(Base58Check.Base58CheckEncoding.DecodePlain(wallet_to_send)); if (friend != null) { nickname = friend.nickname; } Utils.sendUiCommand(webView, "addRecipient", nickname, wallet_to_send); return; } else if (result.Contains(":send")) { // Check for transaction request string[] split = result.Split(new string[] { ":send:" }, StringSplitOptions.None); if (split.Count() > 1) { string wallet_to_send = split[0]; string nickname = wallet_to_send; Friend friend = FriendList.getFriend(Base58Check.Base58CheckEncoding.DecodePlain(wallet_to_send)); if (friend != null) { nickname = friend.nickname; } Utils.sendUiCommand(webView, "addRecipient", nickname, wallet_to_send); return; } } else { // Handle direct addresses string wallet_to_send = result; if (Address.validateChecksum(Base58Check.Base58CheckEncoding.DecodePlain(wallet_to_send))) { string nickname = wallet_to_send; Friend friend = FriendList.getFriend(Base58Check.Base58CheckEncoding.DecodePlain(wallet_to_send)); if (friend != null) { nickname = friend.nickname; } Utils.sendUiCommand(webView, "addRecipient", nickname, wallet_to_send); return; } } }
private static void handleRequestFunds(byte[] sender_wallet, string amount) { // Retrieve the corresponding contact Friend friend = FriendList.getFriend(sender_wallet); if (friend == null) { return; } FriendList.addMessageWithType(FriendMessageType.requestFunds, sender_wallet, amount); }
private static void handleSentFunds(byte[] id, byte[] sender_wallet, string txid) { // Retrieve the corresponding contact Friend friend = FriendList.getFriend(sender_wallet); if (friend == null) { return; } FriendList.addMessageWithType(id, FriendMessageType.sentFunds, sender_wallet, txid); }
// Sends the nickname back to the sender, detects if it should fetch the sender's nickname and fetches it automatically private static void handleGetNick(byte[] sender_wallet, string text) { Friend friend = FriendList.getFriend(sender_wallet); if (friend == null) { byte[] pub_k = FriendList.findContactPubkey(sender_wallet); if (pub_k == null) { Console.WriteLine("Contact {0} not found in presence list!", Base58Check.Base58CheckEncoding.EncodePlain(sender_wallet)); foreach (Presence pr in PresenceList.presences) { Console.WriteLine("Presence: {0}", Base58Check.Base58CheckEncoding.EncodePlain(pr.wallet)); } return; } friend = new Friend(sender_wallet, pub_k, "Unknown"); FriendList.addFriend(sender_wallet, pub_k, "Unknown"); SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.getNick, new byte[1]); // Also request the nickname of the sender // Prepare the message and send to the S2 nodes StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.info; message.recipient = sender_wallet; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); string relayip = friend.searchForRelay(); StreamProcessor.sendMessage(message, relayip); } SpixiMessage reply_spixi_message = new SpixiMessage(SpixiMessageCode.nick, Encoding.UTF8.GetBytes(Node.localStorage.nickname)); // Send the nickname message to the S2 nodes StreamMessage reply_message = new StreamMessage(); reply_message.type = StreamMessageCode.info; reply_message.recipient = friend.walletAddress; reply_message.sender = Node.walletStorage.getPrimaryAddress(); reply_message.transaction = new byte[1]; reply_message.sigdata = new byte[1]; reply_message.data = reply_spixi_message.getBytes(); StreamProcessor.sendMessage(reply_message, friend.searchForRelay()); return; }
// Called when receiving read confirmation from the message recipient public static void handleMsgRead(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { friend.setMessageRead(data.id); } else { Logging.error("Received Message read for an unknown friend."); } }
public static void handlefileData(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { TransferManager.receiveFileData(data.data, sender); } else { Logging.error("Received file data from an unknown friend."); } }
private void HandlePickSucceeded(object sender, SPIXI.EventArgs <string> e) { string wallet_to_send = e.Value; string nickname = wallet_to_send; Friend friend = FriendList.getFriend(Base58Check.Base58CheckEncoding.DecodePlain(wallet_to_send)); if (friend != null) { nickname = friend.nickname; } webView.Eval(string.Format("addRecipient('{0}','{1}')", nickname, wallet_to_send)); Navigation.PopModalAsync(); }
public static void completeFileTransfer(byte[] sender, string uid) { Friend friend = FriendList.getFriend(sender); if (friend == null) { return; } if (friend.chat_page != null) { friend.chat_page.updateFile(uid, "100", true); } }
// Sends the nickname back to the sender, detects if it should fetch the sender's nickname and fetches it automatically private static void handleGetNick(byte[] sender_wallet, string text) { Friend friend = FriendList.getFriend(sender_wallet); if (friend == null) { Console.WriteLine("Contact {0} not found in presence list!", Base58Check.Base58CheckEncoding.EncodePlain(sender_wallet)); return; } sendNickname(friend); return; }
private void sendPayment(string txfee) { Logging.info("Preparing to send payment"); //Navigation.PopAsync(Config.defaultXamarinAnimations); // Create an ixian transaction and send it to the dlt network IxiNumber fee = ConsensusConfig.transactionPrice; byte[] from = Node.walletStorage.getPrimaryAddress(); byte[] pubKey = Node.walletStorage.getPrimaryPublicKey(); Logging.info("Preparing tx"); Transaction transaction = new Transaction((int)Transaction.Type.Normal, fee, to_list, from, null, pubKey, IxianHandler.getHighestKnownNetworkBlockHeight()); Logging.info("Broadcasting tx"); IxianHandler.addTransaction(transaction); Logging.info("Adding to cache"); // Add the unconfirmed transaction to the cache TransactionCache.addUnconfirmedTransaction(transaction); Logging.info("Showing payment details"); // Send message to recipients foreach (var entry in to_list) { Friend friend = FriendList.getFriend(entry.Key); if (friend != null) { FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.sentFunds, entry.Key, transaction.id, true); SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.sentFunds, Encoding.UTF8.GetBytes(transaction.id)); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.info; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); message.id = friend_message.id; StreamProcessor.sendMessage(friend, message); } } // Show the payment details Navigation.PushAsync(new WalletSentPage(transaction, false), Config.defaultXamarinAnimations); }
// Thread for checking offline message queue private static void sendOfflineMessages() { List <StreamMessage> cache = new List <StreamMessage>(); bool writeToFile = false; lock (offlineMessages) { // Go through each message foreach (StreamMessage message in offlineMessages) { try { // Extract the public key from the Presence List Friend f = FriendList.getFriend(message.recipient); if (f == null) { cache.Add(message); continue; } // Send the message if (sendMessage(f, message, false)) { // Add the message to the removal cache cache.Add(message); } }catch (Exception e) { Logging.error("Exception occured while trying to send offline message {0}", e); } } // Check the removal cache for messages foreach (StreamMessage message in cache) { writeToFile = true; offlineMessages.Remove(message); } } // Finally, clear the removal cache cache.Clear(); // Save changes to the offline messages file if (writeToFile) { Node.localStorage.writeOfflineMessagesFile(offlineMessages); } }
// Called when receiving file headers from the message recipient public static void handleFileHeader(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { FileTransfer transfer = TransferManager.prepareIncomingFileTransfer(data.data, sender); string message_data = string.Format("{0}:{1}", transfer.uid, transfer.fileName); FriendList.addMessageWithType(data.id, FriendMessageType.fileHeader, sender, message_data); } else { Logging.error("Received File Header from an unknown friend."); } }
// Called when receiving file headers from the message recipient public static void handleFileHeader(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { Logging.info("Received file header"); FileTransfer transfer = new FileTransfer(data.data); FriendList.addMessageWithType(data.id, FriendMessageType.fileHeader, sender, transfer.name); } else { Logging.error("Received File Header for an unknown friend."); } }
public static void requestFileData(byte[] sender, string uid, ulong packet_number) { Logging.info("Requesting File Data, packet #{0}", packet_number); Friend friend = FriendList.getFriend(sender); if (friend == null) { return; } using (MemoryStream m = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(m)) { if (uid != null) { writer.Write(uid); } writer.Write(packet_number); } SpixiMessage spixi_message = new SpixiMessage(Guid.NewGuid().ToByteArray(), SpixiMessageCode.requestFileData, m.ToArray()); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); StreamProcessor.sendMessage(friend, message); if (friend.chat_page != null) { FileTransfer transfer = TransferManager.getIncomingTransfer(uid); if (transfer == null) { return; } ulong totalPackets = transfer.fileSize / (ulong)Config.packetDataSize; ulong fp = 100 / totalPackets * (packet_number - 1); friend.chat_page.updateFile(uid, fp.ToString(), false); } } }
// Called when receiving encryption keys from the S2 node public static void handleReceivedKeys(byte[] sender, byte[] data) { Friend friend = FriendList.getFriend(sender); if (friend != null) { friend.handshakeStatus = 3; friend.receiveKeys(data); } else { // TODO TODO TODO handle this edge case, by displaying request to add notification to user Logging.error("Received keys for an unknown friend."); } }
private void onNetworkData(string data) { foreach (byte[] address in userAddresses) { Friend f = FriendList.getFriend(address); if (f != null) { // TODO TODO TODO probably a different encoding should be used for data StreamProcessor.sendAppData(f, sessionId, UTF8Encoding.UTF8.GetBytes(data)); } else { Logging.error("Friend {0} does not exist in the friend list.", Base58Check.Base58CheckEncoding.EncodePlain(address)); } } }
// Called when receiving received confirmation from the message recipient public static void handleMsgReceived(byte[] sender, SpixiMessage data) { Friend friend = FriendList.getFriend(sender); Logging.info("Received msg received confirmation for: {0}, data: {1}", Base58Check.Base58CheckEncoding.EncodePlain(sender), Crypto.hashToString(data.id)); if (friend != null) { Logging.info("Friend's handshake status is {0}", friend.handshakeStatus); if (data.id.SequenceEqual(new byte[] { 0 })) { if (friend.handshakeStatus == 0) { friend.handshakeStatus = 1; Logging.info("Set handshake status to {0}", friend.handshakeStatus); } return; } if (data.id.SequenceEqual(new byte[] { 2 })) { if (friend.handshakeStatus == 2) { friend.handshakeStatus = 3; Logging.info("Set handshake status to {0}", friend.handshakeStatus); } return; } if (data.id.SequenceEqual(new byte[] { 4 })) { if (friend.handshakeStatus == 3) { friend.handshakeStatus = 4; Logging.info("Set handshake status to {0}", friend.handshakeStatus); } return; } friend.setMessageReceived(data.id); } else { Logging.error("Received Message received confirmation for an unknown friend."); } }
private void onLoad() { //webView.Eval(string.Format("setBalance('{0}')", Node.balance)); if (transaction == null) { // This should never happen. Perhaps close this screen? } else { string nickname = "Unknown"; Friend friend = null; byte[] addr = transaction.toList.Keys.First(); // Check if this is a received payment if (addr.SequenceEqual(Node.walletStorage.getPrimaryAddress())) { webView.Eval("setReceivedMode()"); // TODO: FIX ME /* friend = FriendList.getFriend(transaction.from); * addr = transaction.from;*/ } else { // This is a sent payment friend = FriendList.getFriend(addr); } if (friend != null) { nickname = friend.nickname; } // Convert unix timestamp string time = Utils.UnixTimeStampToString(Convert.ToDouble(transaction.timeStamp)); webView.Eval(string.Format("setInitialData('{0}', '{1}', '{2}', '{3}', '{4}')", transaction.amount.ToString(), transaction.fee.ToString(), Base58Check.Base58CheckEncoding.EncodePlain(addr), nickname, time)); } checkTransaction(); Device.StartTimer(TimeSpan.FromSeconds(2), () => { return(checkTransaction()); // True = Repeat again, False = Stop the timer }); }
private static int cooldownPeriod = 60; // cooldown period in seconds public static bool sendPushMessage(StreamMessage msg, bool push) { string receiver = Base58Check.Base58CheckEncoding.EncodePlain(msg.recipient); string sender = Base58Check.Base58CheckEncoding.EncodePlain(msg.sender); string data = HttpUtility.UrlEncode(Convert.ToBase64String(msg.getBytes())); string pub_key = ""; if (msg.id.Length == 1 && msg.id[0] == 1) { pub_key = HttpUtility.UrlEncode(Convert.ToBase64String(Node.walletStorage.getPrimaryPublicKey())); } Friend f = FriendList.getFriend(msg.recipient); if (f == null) { return(true); // return true to skip sending this message and remove it from the queue } string URI = String.Format("{0}/push.php", Config.pushServiceUrl); string parameters = String.Format("tag={0}&data={1}&pk={2}&push={3}&fa={4}", receiver, data, pub_key, push, sender); using (WebClient client = new WebClient()) { try { client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; string htmlCode = client.UploadString(URI, parameters); if (htmlCode.Equals("OK")) { if (msg.id.Length == 1 && msg.id[0] >= f.handshakeStatus) { f.handshakePushed = true; FriendList.saveToStorage(); } return(true); } }catch (Exception e) { Logging.error("Exception occured in sendPushMessage: " + e); } } return(false); }
public void displayAppRequests() { if (_webView == null) { return; } Utils.sendUiCommand(_webView, "clearAppRequests"); var app_pages = Node.customAppManager.getAppPages(); lock (app_pages) { foreach (CustomAppPage page in app_pages.Values) { if (page.accepted) { continue; } Friend f = FriendList.getFriend(page.hostUserAddress); CustomApp app = Node.customAppManager.getApp(page.appId); string text = string.Format(SpixiLocalization._SL("global-app-wants-to-use"), f.nickname, app.name); Utils.sendUiCommand(_webView, "addAppRequest", Crypto.hashToString(page.sessionId), text, SpixiLocalization._SL("global-app-accept"), SpixiLocalization._SL("global-app-reject")); } if (VoIPManager.isInitiated()) { if (VoIPManager.currentCallAccepted) { if (VoIPManager.currentCallCalleeAccepted) { displayCallBar(VoIPManager.currentCallSessionId, SpixiLocalization._SL("global-call-in-call") + " - " + VoIPManager.currentCallContact.nickname, VoIPManager.currentCallStartedTime); } else { displayCallBar(VoIPManager.currentCallSessionId, SpixiLocalization._SL("global-call-dialing") + " " + VoIPManager.currentCallContact.nickname + "...", 0); } } else { Friend f = VoIPManager.currentCallContact; string text = SpixiLocalization._SL("global-call-incoming") + " - " + f.nickname; string accept_html = "<div style='background:#2fd63b;border-radius:16px;width:64px;height:64px;display:table-cell;vertical-align:middle;text-align:center;'><i class='fas fa-phone'></i></div>"; string reject_html = "<div style='background:#de0a61;border-radius:16px;width:64px;height:64px;display:table-cell;vertical-align:middle;text-align:center;'><i class='fas fa-phone-slash'></i></div>"; Utils.sendUiCommand(_webView, "addAppRequest", Crypto.hashToString(VoIPManager.currentCallSessionId), text, accept_html, reject_html); } } } }