Commit 9b1d7f1c authored by Ghislain MARY's avatar Ghislain MARY

New method for file upload.

parent eafec331
......@@ -164,6 +164,13 @@ namespace Linphone.Agents
{
}
/// <summary>
/// Callback for LinphoneCoreListener
/// </summary>
public void FileTransferProgressIndication(LinphoneChatMessage message, int offset, int total)
{
}
/// <summary>
/// Callback for LinphoneCoreListener
/// </summary>
......
......@@ -154,7 +154,9 @@ namespace Linphone
Idle = 0,
InProgress = 1,
Delivered = 2,
NotDelivered = 3
NotDelivered = 3,
FileTransferError = 4,
FileTransferDone = 5
};
public enum class DeclineReason : int
......
......@@ -49,6 +49,29 @@ Linphone::Core::LinphoneChatMessage^ Linphone::Core::LinphoneChatRoom::CreateLin
return chatMessage;
}
Linphone::Core::LinphoneChatMessage^ Linphone::Core::LinphoneChatRoom::CreateFileTransferMessage(Platform::String^ type, Platform::String^ subtype, Platform::String^ name, int size, Platform::String^ filepath)
{
TRACE; gApiLock.Lock();
const char *ctype = Linphone::Core::Utils::pstoccs(type);
const char *csubtype = Linphone::Core::Utils::pstoccs(subtype);
const char *cname = Linphone::Core::Utils::pstoccs(name);
const char *cfilepath = Linphone::Core::Utils::pstoccs(filepath);
LinphoneContent content;
memset(&content, 0, sizeof(content));
content.type = (char *)ctype;
content.subtype = (char *)csubtype;
content.size = size;
content.name = (char *)cname;
Linphone::Core::LinphoneChatMessage^ chatMessage = (Linphone::Core::LinphoneChatMessage^) Linphone::Core::Utils::CreateLinphoneChatMessage(
linphone_chat_room_create_file_transfer_message_from_file(this->room, &content, cfilepath));
delete(ctype);
delete(csubtype);
delete(cname);
delete(cfilepath);
gApiLock.Unlock();
return chatMessage;
}
Platform::Boolean Linphone::Core::LinphoneChatRoom::IsRemoteComposing()
{
TRACE; gApiLock.Lock();
......
......@@ -73,6 +73,17 @@ namespace Linphone
/// </summary>
void DeleteMessageFromHistory(Linphone::Core::LinphoneChatMessage^ message);
/// <summary>
/// Creates a LinphoneChatMessage to transfer a file.
/// </summary>
/// <param name="type">MIME type of the file to transfer</param>
/// <param name="subtype">MIME subtype of the file to transfer</param>
/// <param name="name">Name of the file to transfer</param>
/// <param name="size">Size in bytes of the file to transfer</param>
/// <param name="filepath">Path to the file to transfer</param>
/// <returns>A new LinphoneChatMessage</returns>
Linphone::Core::LinphoneChatMessage^ CreateFileTransferMessage(Platform::String^ type, Platform::String^ subtype, Platform::String^ name, int size, Platform::String^ filepath);
private:
friend class Linphone::Core::Utils;
friend ref class Linphone::Core::LinphoneCore;
......
......@@ -16,6 +16,7 @@
#include "ApiLock.h"
#include <collection.h>
using namespace Microsoft::WRL;
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation;
......@@ -1665,6 +1666,21 @@ void composing_received(LinphoneCore *lc, LinphoneChatRoom *room)
Linphone::Core::gApiLock.LeaveListener();
}
void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent *content, size_t offset, size_t total) {
Linphone::Core::gApiLock.EnterListener();
Linphone::Core::LinphoneCoreListener^ listener = Linphone::Core::Globals::Instance->LinphoneCore->CoreListener;
if (listener != nullptr)
{
Linphone::Core::RefToPtrProxy<Linphone::Core::LinphoneChatMessage^> *proxy = reinterpret_cast< Linphone::Core::RefToPtrProxy<Linphone::Core::LinphoneChatMessage^> *>(linphone_chat_message_get_user_data(message));
Linphone::Core::LinphoneChatMessage^ lMessage = (proxy) ? proxy->Ref() : nullptr;
if (lMessage == nullptr) {
lMessage = (Linphone::Core::LinphoneChatMessage^)Linphone::Core::Utils::CreateLinphoneChatMessage(message);
}
listener->FileTransferProgressIndication(lMessage, (int)offset, total);
}
Linphone::Core::gApiLock.LeaveListener();
}
void log_collection_upload_progress_indication(LinphoneCore *lc, size_t progress) {
Linphone::Core::gApiLock.EnterListener();
Linphone::Core::LinphoneCoreListener^ listener = Linphone::Core::Globals::Instance->LinphoneCore->CoreListener;
......@@ -1746,6 +1762,7 @@ void Linphone::Core::LinphoneCore::Init()
vtable->call_stats_updated = call_stats_updated;
vtable->message_received = message_received;
vtable->is_composing_received = composing_received;
vtable->file_transfer_progress_indication = file_transfer_progress_indication;
vtable->log_collection_upload_progress_indication = log_collection_upload_progress_indication;
vtable->log_collection_upload_state_changed = log_collection_upload_state_changed;
......
......@@ -84,6 +84,14 @@ namespace Linphone
/// <param name="room">The room for which the composing status has been updated</param>
void ComposingReceived(LinphoneChatRoom^ room);
/// <summary>
/// Callback method called to notify the progression of a file transfer.
/// </summary>
/// <param name="message">The chat message</param>
/// <param name="offset">The number of bytes sent/received since the beginning of the file transfer</param>
/// <param name="total">The total number of bytes to be sent/received</param>
void FileTransferProgressIndication(LinphoneChatMessage^ message, int offset, int total);
/// <summary>
/// Callback method called when the status of the current log upload changes.
/// </summary>
......
......@@ -32,4 +32,5 @@ display=0
[misc]
history_max_size=30
max_calls=1
file_transfer_server_url=https://www.linphone.org:444/lft.php
log_collection_upload_server_url=https://www.linphone.org:444/lft.php
......@@ -1039,6 +1039,14 @@ namespace Linphone.Model
});
}
/// <summary>
/// Callback for LinphoneCoreListener
/// </summary>
public void FileTransferProgressIndication(LinphoneChatMessage message, int offset, int total)
{
Logger.Msg(String.Format("FileTransferProgressIndication: {0}/{1}", offset, total));
}
/// <summary>
/// Callback for LinphoneCoreListener
/// </summary>
......
......@@ -111,7 +111,7 @@ namespace Linphone.Model
/// <param name="image">The bitmap image to save</param>
/// <param name="fileName">The file's name to use</param>
/// <returns>true if the operation succeeds</returns>
public static bool SaveImageInLocalFolder(BitmapImage image, string fileName)
public static string SaveImageInLocalFolder(BitmapImage image, string fileName)
{
try
{
......@@ -129,12 +129,12 @@ namespace Linphone.Model
file.Flush();
file.Close();
bitmap = null;
return true;
return file.Name;
}
}
}
catch { }
return false;
return null;
}
}
}
......@@ -22,6 +22,7 @@ using System.IO.IsolatedStorage;
using System.Net.Http.Headers;
using Microsoft.Xna.Framework.Media;
using Linphone.Agents;
using Windows.Storage;
namespace Linphone.Views
{
......@@ -82,6 +83,8 @@ namespace Linphone.Views
BuildLocalizedApplicationBar();
}
private Task onNavigatedToTask = null;
/// <summary>
/// Method called when the page is displayed.
/// Check if the uri contains a sip address, if yes, it displays the matching chat history.
......@@ -137,6 +140,12 @@ namespace Linphone.Views
}
scrollToBottom();
if (onNavigatedToTask != null)
{
onNavigatedToTask.Start();
onNavigatedToTask = null;
}
}
private void MessageBox_TextChanged(object sender, string text)
......@@ -224,7 +233,6 @@ namespace Linphone.Views
if (chatRoom != null)
{
LinphoneChatMessage chatMessage = chatRoom.CreateLinphoneChatMessage(message);
long time = chatMessage.GetTime();
chatRoom.SendMessage(chatMessage, this);
DateTime date = new DateTime(chatMessage.GetTime() * TimeSpan.TicksPerSecond).AddYears(1969);
......@@ -235,89 +243,12 @@ namespace Linphone.Views
}
}
private async Task<string> UploadImageMessage(BitmapImage image, string filePath)
{
string fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1);
//Copy image in local folder
Utils.SaveImageInLocalFolder(image, fileName);
//Upload the image
string response;
string boundary = "----------" + DateTime.Now.Ticks.ToString();
using (var client = new HttpClient())
{
_httpPostClient = client;
using (var content = new MultipartFormDataContent(boundary))
{
MemoryStream ms = new MemoryStream();
WriteableBitmap bitmap = new WriteableBitmap(image);
Extensions.SaveJpeg(bitmap, ms, image.PixelWidth, image.PixelHeight, 0, SENT_IMAGES_QUALITY);
ms.Flush();
ms.Position = 0;
StreamContent streamContent = new StreamContent(ms);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"userfile\"",
FileName = "\"" + fileName + "\""
};
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(streamContent);
using (var message = await client.PostAsync(Customs.PictureUploadScriptURL, content))
{
message.EnsureSuccessStatusCode();
response = await message.Content.ReadAsStringAsync();
}
}
}
return response;
}
private async void SendImageMessage(string localFileName, BitmapImage image)
{
try
{
ProgressPopup.Visibility = Visibility.Visible;
MessageBox.Visibility = Visibility.Collapsed;
AddCancelUploadButtonInAppBar();
string url = await UploadImageMessage(image, localFileName);
if (url == null || url.Length == 0)
{
return;
}
if (chatRoom != null)
{
LinphoneChatMessage chatMessage = chatRoom.CreateLinphoneChatMessage("");
chatMessage.SetExternalBodyUrl(url);
long time = chatMessage.GetTime();
chatRoom.SendMessage(chatMessage, this);
DateTime date = new DateTime(chatMessage.GetTime() * TimeSpan.TicksPerSecond).AddYears(1969);
OutgoingChatBubble bubble = new OutgoingChatBubble(chatMessage, image, FormatDate(date));
bubble.MessageDeleted += bubble_MessageDeleted;
MessagesList.Children.Add(bubble);
scrollToBottom();
}
}
catch { }
finally
{
ProgressPopup.Visibility = Visibility.Collapsed;
MessageBox.Visibility = Visibility.Visible;
AddSendButtonsToAppBar();
}
}
/// <summary>
/// Callback called by LinphoneCore when the state of a sent message changes.
/// </summary>
public void MessageStateChanged(LinphoneChatMessage message, LinphoneChatMessageState state)
{
string messageText = message.GetText();
string externalBodyUrl = message.GetExternalBodyUrl();
Logger.Msg("[Chat] Message " + messageText + ", state changed: " + state.ToString());
if (state == LinphoneChatMessageState.InProgress)
{
......@@ -327,6 +258,9 @@ namespace Linphone.Views
Dispatcher.BeginInvoke(() =>
{
ProgressPopup.Visibility = Visibility.Collapsed;
MessageBox.Visibility = Visibility.Visible;
AddSendButtonsToAppBar();
try
{
ChatBubble bubble = (ChatBubble)MessagesList.Children.Where(b => ((ChatBubble)b).ChatMessage.Equals(message)).Last();
......@@ -339,6 +273,43 @@ namespace Linphone.Views
});
}
private void CreateChatRoom()
{
sipAddress = NewChatSipAddress.Text;
if (!sipAddress.Contains("@"))
{
if (LinphoneManager.Instance.LinphoneCore.GetProxyConfigList().Count > 0)
{
LinphoneProxyConfig config = LinphoneManager.Instance.LinphoneCore.GetProxyConfigList()[0] as LinphoneProxyConfig;
sipAddress += "@" + config.GetDomain();
}
else
{
System.Windows.MessageBox.Show(AppResources.InvalidSipAddressError, AppResources.GenericError, MessageBoxButton.OK);
return;
}
}
ContactManager.Instance.FindContact(sipAddress);
ContactName.Text = sipAddress;
ContactName.Visibility = Visibility.Visible;
NewChat.Visibility = Visibility.Collapsed;
try
{
chatRoom = LinphoneManager.Instance.LinphoneCore.GetOrCreateChatRoom(sipAddress);
if (chatRoom.GetHistorySize() > 0)
{
DisplayPastMessages(chatRoom.GetHistory());
}
}
catch
{
Logger.Err("Can't create chat room for sip address {0}", sipAddress);
throw;
}
}
private void cancel_Click_1(object sender, EventArgs e)
{
if (_httpPostClient != null)
......@@ -352,41 +323,7 @@ namespace Linphone.Views
{
if (chatRoom == null) //This code will be executed only in case of new conversation
{
sipAddress = NewChatSipAddress.Text;
if (!sipAddress.Contains("@"))
{
if (LinphoneManager.Instance.LinphoneCore.GetProxyConfigList().Count > 0)
{
LinphoneProxyConfig config = LinphoneManager.Instance.LinphoneCore.GetProxyConfigList()[0] as LinphoneProxyConfig;
sipAddress += "@" + config.GetDomain();
}
else
{
System.Windows.MessageBox.Show(AppResources.InvalidSipAddressError, AppResources.GenericError, MessageBoxButton.OK);
return;
}
}
ContactManager.Instance.FindContact(sipAddress);
ContactName.Text = sipAddress;
ContactName.Visibility = Visibility.Visible;
NewChat.Visibility = Visibility.Collapsed;
try
{
chatRoom = LinphoneManager.Instance.LinphoneCore.GetOrCreateChatRoom(sipAddress);
if (chatRoom.GetHistorySize() > 0)
{
DisplayPastMessages(chatRoom.GetHistory());
}
}
catch
{
Logger.Err("Can't create chat room for sip address {0}", sipAddress);
throw;
}
CreateChatRoom();
}
if (chatRoom != null)
......@@ -411,15 +348,44 @@ namespace Linphone.Views
private void attach_image_Click_1(object sender, EventArgs e)
{
PhotoChooserTask task = new PhotoChooserTask();
task.Completed += task_Completed;
task.Completed += imageSelectionTask_Completed;
task.ShowCamera = true;
task.Show();
}
private void task_Completed(object sender, PhotoResult e)
private void InitiateImageUpload(string filePath, string fileName)
{
BaseModel.UIDispatcher.BeginInvoke(() =>
{
if (chatRoom == null) //This code will be executed only in case of new conversation
{
CreateChatRoom();
}
if (chatRoom != null)
{
ProgressPopup.Visibility = Visibility.Visible;
MessageBox.Visibility = Visibility.Collapsed;
AddCancelUploadButtonInAppBar();
FileInfo fileInfo = new FileInfo(filePath);
LinphoneChatMessage msg = chatRoom.CreateFileTransferMessage("application", "octet-stream", fileName, (int)fileInfo.Length, filePath);
chatRoom.SendMessage(msg, this);
}
else
{
ProgressPopup.Visibility = Visibility.Collapsed;
MessageBox.Visibility = Visibility.Visible;
AddSendButtonsToAppBar();
System.Windows.MessageBox.Show(AppResources.ChatRoomCreationError, AppResources.GenericError, MessageBoxButton.OK);
}
});
}
private void imageSelectionTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
string fileName = e.OriginalFileName.Substring(e.OriginalFileName.LastIndexOf("\\") + 1);
BitmapImage image = new BitmapImage();
image.SetSource(e.ChosenPhoto);
......@@ -445,10 +411,11 @@ namespace Linphone.Views
bm.SaveJpeg(ms, w, h, 0, 100);
image.SetSource(ms);
}
MessageBox.SetImage(image);
string fileName = e.OriginalFileName.Substring(e.OriginalFileName.LastIndexOf("\\") + 1);
MessageBox.ImageName = fileName;
EnableAppBarSendMessageButton(true);
string filePath = Utils.SaveImageInLocalFolder(image, fileName);
if (filePath != null)
{
onNavigatedToTask = new Task(() => InitiateImageUpload(filePath, fileName));
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment