Tutorial for LinphoneSDK x UWP - C#

This commit is contained in:
Anthony Gauchy
2020-12-10 17:20:19 +01:00
parent 50483699b5
commit 29f4bbef5c
215 changed files with 13724 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
<Page
x:Class="_07_AdvancedChat.Views.CallsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="{ThemeResource SystemAccentColorLight3}" Padding="10">
<TextBlock x:Name="HelloText" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{ThemeResource HeaderTextBlockStyle}" Text="Hello " />
</Border>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" VerticalAlignment="Center" Margin="20">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="URI to call : " />
<TextBox x:Name="UriToCall" Width="350" MinWidth="350" MaxWidth="350" Text="sip:" />
</StackPanel>
<Button x:Name="CallButton" Content="Call" Click="CallClick" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5" />
<TextBlock x:Name="CallText" Text="Your call state is : Idle" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10">
<Button x:Name="HangOut" Content="Hang out" Click="HangOutClick" IsEnabled="False" />
<Button x:Name="Sound" Content="Switch off Sound" Click="SoundClick" IsEnabled="False" />
<Button x:Name="Camera" Content="Switch on Camera" Click="CameraClick" IsEnabled="False" />
<Button x:Name="Mic" Content="Mute" Click="MicClick" IsEnabled="False" />
</StackPanel>
</StackPanel>
<Grid Grid.Row="1" x:Name="VideoGrid" Canvas.ZIndex="-1" Background="Black" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<SwapChainPanel x:Name="VideoSwapChainPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Grid.RowSpan="3" />
<SwapChainPanel x:Name="PreviewSwapChainPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="2" Grid.Row="0" Grid.RowSpan="3">
</SwapChainPanel>
</Grid>
<StackPanel Grid.Row="2" x:Name="IncomingCallStackPanel" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Collapsed" Margin="10">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="You have a call from :" />
<TextBlock x:Name="IncommingCallText" Text="" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="Answer" Content="Answer" Click="AnswerClick" />
<Button x:Name="Decline" Content="Decline" Click="DeclineClick" />
</StackPanel>
</StackPanel>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using _07_AdvancedChat.Service;
using Linphone;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace _07_AdvancedChat.Views
{
public sealed partial class CallsPage : Page
{
private CoreService CoreService { get; } = CoreService.Instance;
private VideoService VideoService { get; } = VideoService.Instance;
private Call IncommingCall;
public CallsPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
VideoService.StopVideoStream();
CoreService.RemoveOnCallStateChangedDelegate(OnCallStateChanged);
base.OnNavigatedFrom(e);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
HelloText.Text += CoreService.Core.DefaultProxyConfig.FindAuthInfo().Username;
CoreService.AddOnCallStateChangedDelegate(OnCallStateChanged);
if (CoreService.Core.CurrentCall != null)
{
OnCallStateChanged(CoreService.Core, CoreService.Core.CurrentCall, CoreService.Core.CurrentCall.State, null);
}
}
private void CallClick(object sender, RoutedEventArgs e)
{
CoreService.Call(UriToCall.Text);
}
private void HangOutClick(object sender, RoutedEventArgs e)
{
CoreService.Core.TerminateAllCalls();
}
private void SoundClick(object sender, RoutedEventArgs e)
{
if (CoreService.SpeakerMutedSwitch())
{
Sound.Content = "Switch on Sound";
}
else
{
Sound.Content = "Switch off Sound";
}
}
private async void CameraClick(object sender, RoutedEventArgs e)
{
await CoreService.CameraEnabledSwitchAsync();
Camera.Content = "Waiting for accept ...";
Camera.IsEnabled = false;
}
private void MicClick(object sender, RoutedEventArgs e)
{
if (CoreService.MicEnabledSwitch())
{
Mic.Content = "Mute";
}
else
{
Mic.Content = "Unmute";
}
}
private void AnswerClick(object sender, RoutedEventArgs e)
{
IncommingCall.Accept();
IncommingCall = null;
}
private void DeclineClick(object sender, RoutedEventArgs e)
{
if (IncommingCall != null)
{
IncommingCall.Decline(Reason.Declined);
IncommingCall = null;
}
}
private void OnCallStateChanged(Core core, Call call, CallState state, string message)
{
CallText.Text = "Your call state is : " + state.ToString();
switch (state)
{
case CallState.IncomingReceived:
IncommingCall = call;
IncomingCallStackPanel.Visibility = Visibility.Visible;
IncommingCallText.Text = " " + call.RemoteAddress.AsString();
break;
case CallState.OutgoingInit:
case CallState.OutgoingProgress:
case CallState.OutgoingRinging:
HangOut.IsEnabled = true;
break;
case CallState.StreamsRunning:
case CallState.UpdatedByRemote:
CallInProgressGuiUpdates();
if (call.CurrentParams.VideoEnabled)
{
StartVideoAndUpdateGui();
}
else
{
StopVideoAndUpdateGui();
}
break;
case CallState.Error:
case CallState.End:
case CallState.Released:
IncommingCall = null;
EndingCallGuiUpdates();
VideoService.StopVideoStream();
break;
}
}
private void StopVideoAndUpdateGui()
{
Camera.Content = "Switch on Camera";
Camera.IsEnabled = true;
VideoGrid.Visibility = Visibility.Collapsed;
VideoService.StopVideoStream();
}
private void StartVideoAndUpdateGui()
{
VideoGrid.Visibility = Visibility.Visible;
Camera.Content = "Switch off Camera";
VideoService.StartVideoStream(VideoSwapChainPanel, PreviewSwapChainPanel);
Camera.IsEnabled = true;
}
private void EndingCallGuiUpdates()
{
IncomingCallStackPanel.Visibility = Visibility.Collapsed;
CallButton.IsEnabled = true;
HangOut.IsEnabled = false;
Sound.IsEnabled = false;
Camera.IsEnabled = false;
Mic.IsEnabled = false;
VideoGrid.Visibility = Visibility.Collapsed;
Camera.Content = "Switch on Camera";
Mic.Content = "Mute";
Sound.Content = "Switch off Sound";
}
private void CallInProgressGuiUpdates()
{
IncomingCallStackPanel.Visibility = Visibility.Collapsed;
CallButton.IsEnabled = false;
HangOut.IsEnabled = true;
Sound.IsEnabled = true;
Camera.IsEnabled = true;
Mic.IsEnabled = true;
}
}
}

View File

@@ -0,0 +1,66 @@
<Page
x:Class="_07_AdvancedChat.Views.ChatPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*" />
<RowDefinition Height="0.9*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock x:Name="ChatHeaderText" Text="Your conversation with : " Style="{ThemeResource HeaderTextBlockStyle}" />
</StackPanel>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="0.70*" />
<RowDefinition Height="0.30*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="auto" MaxWidth="350" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Padding="10,0,10,0">
<TextBlock x:Name="PeerUsername" Text="Peer user-name : " />
<TextBlock x:Name="YourUsername" Text="Your user-name : " HorizontalAlignment="Right" />
</Grid>
<ScrollViewer Grid.Row="1" x:Name="MessagesScroll">
<StackPanel Padding="10"
x:Name="MessagesList"
Orientation="Vertical"
VerticalAlignment="Bottom">
</StackPanel>
</ScrollViewer>
<Border x:Name="GroupChatDisplayBorder" BorderBrush="{ThemeResource SystemAccentColorLight3}"
BorderThickness="1,0,0,0" Padding="5" Grid.Column="1" Grid.RowSpan="2" Visibility="Collapsed" />
<Grid Grid.Row="2" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.80*" />
<ColumnDefinition Width="0.20*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" x:Name="OutgoingMessageText" Text="" AcceptsReturn="True" TextWrapping="Wrap" />
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" x:Name="OutgoingMessageButton" Click="OutgoingMessageButton_Click" Content="Send" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="1" />
<Button Grid.Row="1" x:Name="SendFileButton" Click="SendFileButton_Click" Content="Send a file" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="1" />
<Button Grid.Row="2" x:Name="SendMultipartButton" Click="SendMultipartButton_Click" Content="Send multipart (text+file)" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="1" />
<CheckBox Grid.Row="3" x:Name="EphemeralCheckBox" Content="Ephemeral mode enable" Checked="EphemeralCheckBox_Checked" Unchecked="EphemeralCheckBox_Unchecked" IsChecked="True" HorizontalAlignment="Center" />
</Grid>
</Grid>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,261 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using _07_AdvancedChat.Controls;
using _07_AdvancedChat.Service;
using Linphone;
using System;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace _07_AdvancedChat.Views
{
public sealed partial class ChatPage : Page
{
private NavigationService NavigationService { get; } = NavigationService.Instance;
private CoreService CoreService { get; } = CoreService.Instance;
private ChatRoom ChatRoom;
public ChatPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ChatRoom = ((ChatRoom)e.Parameter);
ChatRoom.Listener.OnMessageReceived += OnMessageReceived;
ChatRoom.Listener.OnConferenceLeft += AddEvent;
ChatRoom.Listener.OnConferenceJoined += AddEvent;
ChatRoom.Listener.OnParticipantDeviceRemoved += AddEvent;
ChatRoom.Listener.OnSubjectChanged += AddEvent;
ChatRoom.Listener.OnParticipantRemoved += AddEvent;
ChatRoom.Listener.OnParticipantAdminStatusChanged += AddEvent;
ChatRoom.Listener.OnParticipantAdded += AddEvent;
ChatRoom.Listener.OnEphemeralEvent += AddEvent;
// In this step we want to test the ephemeral messages. This feature is only
// available if you are using in a Flexisip backend.
if (ChatRoomBackend.FlexisipChat.Equals(ChatRoom.CurrentParams.Backend) && !ChatRoom.EphemeralEnabled)
{
// In this step when the ephemeral feature is available we enable it
// by default. Just set the EphemeralEnabled to true to activate the
// ephemeral mode, after this point every message send will be marked
// as ephemeral
ChatRoom.EphemeralEnabled = true;
// You can choose how many times you want the message to be displayed before
// getting destroyed with EphemeralLifetime, the value is in second.
// Here we set a low value for testing purpose.
ChatRoom.EphemeralLifetime = 15;
// At any time you can choose to disable the ephemeral mode moving EphemeralEnabled to false.
// See the EphemeralCheckBox_Unchecked method.
}
else if (!ChatRoomBackend.FlexisipChat.Equals(ChatRoom.CurrentParams.Backend))
{
// If the backend is not a Flexisip one we hide the ephemeral feature in the ChatPage
// because it doesn't support it.
EphemeralCheckBox.Visibility = Visibility.Collapsed;
}
if (ChatRoom.PeerAddress != null)
{
UpdateGUI();
}
else
{
ChatHeaderText.Text = "Creation in progress";
ChatRoom.Listener.OnConferenceJoined += OnConferenceJoin;
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ChatRoom.Listener.OnMessageReceived -= OnMessageReceived;
ChatRoom.Listener.OnConferenceLeft -= AddEvent;
ChatRoom.Listener.OnConferenceJoined -= AddEvent;
ChatRoom.Listener.OnParticipantDeviceRemoved -= AddEvent;
ChatRoom.Listener.OnSubjectChanged -= AddEvent;
ChatRoom.Listener.OnParticipantRemoved -= AddEvent;
ChatRoom.Listener.OnParticipantAdminStatusChanged -= AddEvent;
ChatRoom.Listener.OnParticipantAdded -= AddEvent;
ChatRoom.Listener.OnConferenceJoined -= OnConferenceJoin;
base.OnNavigatedFrom(e);
}
private void OnConferenceJoin(ChatRoom chatRoom, EventLog eventLog)
{
UpdateGUI();
}
private void UpdateGUI()
{
ChatHeaderText.Text = "Your conversation with : " + ChatRoom.PeerAddress.Username;
foreach (EventLog eventLog in ChatRoom.GetHistoryEvents(0))
{
if (EventLogType.ConferenceChatMessage.Equals(eventLog.Type))
{
AddMessage(eventLog.ChatMessage);
}
else
{
AddEvent(null, eventLog);
}
}
ChatRoom.MarkAsRead();
NavigationService.CurrentNavigationRoot.UpdateUnreadMessageCount();
NavigationService.CurrentChatspage.UpdateChatRooms();
PeerUsername.Text += ChatRoom.PeerAddress.Username;
YourUsername.Text += ChatRoom.LocalAddress.Username;
// We only display the GroupChatDisplay if we are in real group chat,
// we don't if it's a OneToOne secure ChatRoom.
if (ChatRoom.HasCapability((int)ChatRoomCapabilities.Conference)
&& !ChatRoom.HasCapability((int)ChatRoomCapabilities.OneToOne))
{
GroupChatDisplay participantsDisplay = new GroupChatDisplay(ChatRoom);
GroupChatDisplayBorder.Child = participantsDisplay;
GroupChatDisplayBorder.Visibility = Visibility.Visible;
}
if (ChatRoom.HasCapability((int)ChatRoomCapabilities.Basic))
{
SendMultipartButton.Visibility = Visibility.Collapsed;
}
}
private void OnMessageReceived(ChatRoom chatRoom, ChatMessage message)
{
if (ChatRoom != null)
{
AddMessage(message);
chatRoom.MarkAsRead();
}
}
private void AddMessage(ChatMessage chatMessage)
{
MessageDisplay messageDisplay = new MessageDisplay(chatMessage);
MessagesList.Children.Add(messageDisplay);
ScrollToBottom();
}
private void AddEvent(ChatRoom chatRoom, EventLog eventLog)
{
EventDisplay eventDisplay = new EventDisplay(eventLog);
MessagesList.Children.Add(eventDisplay);
ScrollToBottom();
}
private void ScrollToBottom()
{
MessagesScroll.UpdateLayout();
MessagesScroll.ChangeView(1, MessagesScroll.ExtentHeight, 1);
}
private void OutgoingMessageButton_Click(object sender, RoutedEventArgs e)
{
if (ChatRoom != null && OutgoingMessageText.Text != null && OutgoingMessageText.Text.Length > 0)
{
ChatMessage chatMessage = ChatRoom.CreateMessage(OutgoingMessageText.Text);
chatMessage.Send();
AddMessage(chatMessage);
}
OutgoingMessageText.Text = "";
}
private async void SendFileButton_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add("*");
StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
Content content = await CoreService.CreateContentFromFile(file);
ChatMessage fileMessage = ChatRoom.CreateFileTransferMessage(content);
fileMessage.Send();
AddMessage(fileMessage);
}
}
private async void SendMultipartButton_Click(object sender, RoutedEventArgs e)
{
if (ChatRoom != null && OutgoingMessageText.Text != null && OutgoingMessageText.Text.Length > 0)
{
ChatMessage multipartMessage = ChatRoom.CreateMessage(OutgoingMessageText.Text);
FileOpenPicker picker = new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
};
picker.FileTypeFilter.Add("*");
StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
Content content = await CoreService.CreateContentFromFile(file);
multipartMessage.AddFileContent(content);
multipartMessage.Send();
AddMessage(multipartMessage);
}
}
OutgoingMessageText.Text = "";
}
private void EphemeralCheckBox_Checked(object sender, RoutedEventArgs e)
{
if (ChatRoom != null)
{
ChatRoom.EphemeralEnabled = true;
}
}
private void EphemeralCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
if (ChatRoom != null)
{
ChatRoom.EphemeralEnabled = false;
}
}
}
}

View File

@@ -0,0 +1,45 @@
<Page
x:Class="_07_AdvancedChat.Views.ChatsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:_07_AdvancedChat.Shared"
xmlns:linphone="using:Linphone"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<local:ChatRoomToStringConverter x:Key="ChatRoomToStringConverter" />
</Page.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Border BorderBrush="{ThemeResource SystemAccentColorLight3}"
BorderThickness="2,2,1,2"
Padding="2">
<StackPanel Grid.Column="0" Orientation="Vertical">
<Button x:Name="NewChatRoom" Click="NewChatRoom_Click" Content="Create a new basic ChatRoom" Tag="false" HorizontalAlignment="Stretch" />
<Button x:Name="NewSecureChatRoom" Click="NewChatRoom_Click" Content="Create a new secure ChatRoom" Tag="true" HorizontalAlignment="Stretch" />
<Button x:Name="NewGroupChatRoom" Click="NewGroupChatRoom_Click" Content="Create a new group ChatRoom" HorizontalAlignment="Stretch" />
<ListView x:Name="ChatRoomsLV" SelectionMode="Single" IsItemClickEnabled="True" ItemClick="ChatRoomsLV_ItemClick">
<ListView.ItemTemplate>
<DataTemplate x:DataType="linphone:ChatRoom">
<StackPanel Orientation="Horizontal">
<Border BorderThickness="1" BorderBrush="{ThemeResource SystemAccentColorLight3}" CornerRadius="10" Margin="0,0,5,0" Padding="3,0,3,0">
<TextBlock Text="{x:Bind UnreadMessagesCount}" FontSize="14" />
</Border>
<TextBlock Text="{x:Bind Converter={StaticResource ChatRoomToStringConverter}}" FontSize="14" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Border>
<Border BorderBrush="{ThemeResource SystemAccentColorLight3}"
BorderThickness="1,2,2,2"
Padding="2"
Grid.Column="1">
<Frame x:Name="ChatRoomFrame" />
</Border>
</Grid>
</Page>

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using _07_AdvancedChat.Service;
using _07_AdvancedChat.Shared;
using Linphone;
using System;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace _07_AdvancedChat.Views
{
public sealed partial class ChatsPage : Page
{
private CoreService CoreService { get; } = CoreService.Instance;
private NavigationService NavigationService { get; } = NavigationService.Instance;
public ChatsPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
NavigationService.CurrentChatspage = this;
UpdateChatRooms();
CoreService.AddOnOnMessageReceivedDelegate(OnMessageReceiveOrSent);
CoreService.AddOnMessageSentDelegate(OnMessageReceiveOrSent);
CoreService.AddOnChatRoomSubjectChangedDelegate(AddOnChatRoomSubjectChanged);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
NavigationService.CurrentChatspage = null;
CoreService.RemoveOnOnMessageReceivedDelegate(OnMessageReceiveOrSent);
CoreService.RemoveOnMessageSentDelegate(OnMessageReceiveOrSent);
CoreService.RemoveOnChatRoomSubjectChangedDelegate(AddOnChatRoomSubjectChanged);
base.OnNavigatedFrom(e);
}
private void OnMessageReceiveOrSent(Core core, ChatRoom chatRoom, ChatMessage message) => UpdateChatRooms();
private void AddOnChatRoomSubjectChanged(Core core, ChatRoom chatRoom) => UpdateChatRooms();
public void UpdateChatRooms()
{
ChatRoom selectedChatRoom = (ChatRoom)ChatRoomsLV.SelectedItem;
ChatRoomsLV.Items.Clear();
foreach (ChatRoom chatRoom in CoreService.Core.ChatRooms)
{
if (chatRoom.HistoryEventsSize > 0)
{
ChatRoomsLV.Items.Add(chatRoom);
if (selectedChatRoom == chatRoom)
{
ChatRoomsLV.SelectedItem = chatRoom;
}
}
}
}
private void ChatRoomsLV_ItemClick(object sender, ItemClickEventArgs e)
{
ChatRoomsLV.SelectedItem = e.ClickedItem;
ChatRoomFrame.Navigate(typeof(ChatPage), e.ClickedItem);
}
private async void NewChatRoom_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
string peerSipAddress = await Utils.InputTextDialogAsync("Enter peer sip address");
bool secure = Boolean.Parse((string)((Button)sender).Tag);
if (!String.IsNullOrWhiteSpace(peerSipAddress))
{
ChatRoom newChatRoom = CoreService.CreateOrGetChatRoom(peerSipAddress, secure);
if (newChatRoom != null)
{
ChatRoomFrame.Navigate(typeof(ChatPage), newChatRoom);
}
else
{
ContentDialog noSettingsDialog = new ContentDialog
{
Title = "ChatRoom creation error",
Content = "An error occurred during ChatRoom creation, check sip address validity and try again.",
CloseButtonText = "OK"
};
await noSettingsDialog.ShowAsync();
}
}
}
private void NewGroupChatRoom_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
ChatRoomFrame.Navigate(typeof(CreateGroupChatRoom));
}
}
}

View File

@@ -0,0 +1,33 @@
<Page
x:Class="_07_AdvancedChat.Views.CreateGroupChatRoom"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:linphone="using:Linphone">
<Grid>
<StackPanel VerticalAlignment="Center">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
<TextBlock Text="Group ChatRoom subject :" />
<TextBox x:Name="Subject" PlaceholderText="A subject" />
<CheckBox x:Name="SecureCheckBox" Content="I want a secure ChatRoom" />
</StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" Margin="0,10,0,10">
<TextBox x:Name="Address" Width="350" MinWidth="350" MaxWidth="350" Text="sip:" />
<Button x:Name="AddAddress" Click="AddAddress_Click" Content="Add" HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
<ListView x:Name="AddressesLV" SelectionMode="None" IsItemClickEnabled="False">
<ListView.ItemTemplate>
<DataTemplate x:DataType="linphone:Address">
<TextBlock Text="{x:Bind AsString()}" FontSize="14" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button x:Name="Create" Click="Create_Click" Content="Create" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10,0,0" />
</StackPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using _07_AdvancedChat.Service;
using Linphone;
using System;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace _07_AdvancedChat.Views
{
public sealed partial class CreateGroupChatRoom : Page
{
private CoreService CoreService { get; } = CoreService.Instance;
private readonly ObservableCollection<Address> addresses = new ObservableCollection<Address>();
public ObservableCollection<Address> DisplayedAddresses
{
get { return this.addresses; }
}
public CreateGroupChatRoom()
{
this.InitializeComponent();
}
private async void Create_Click(object sender, RoutedEventArgs e)
{
ChatRoom newChatRoom = CoreService.CreateGroupChatRoom(DisplayedAddresses, Subject.Text, SecureCheckBox.IsChecked ?? false);
if (newChatRoom != null)
{
this.Frame.Navigate(typeof(ChatPage), newChatRoom);
}
else
{
ContentDialog noSettingsDialog = new ContentDialog
{
Title = "ChatRoom creation error",
Content = "An error occurred during group ChatRoom creation, check sip addresses validity and try again.",
CloseButtonText = "OK"
};
await noSettingsDialog.ShowAsync();
}
}
private void AddAddress_Click(object sender, RoutedEventArgs e)
{
if (!String.IsNullOrWhiteSpace(Address.Text))
{
DisplayedAddresses.Add(CoreService.Core.InterpretUrl(Address.Text));
AddressesLV.ItemsSource = DisplayedAddresses;
}
}
}
}

View File

@@ -0,0 +1,34 @@
<Page
x:Class="_07_AdvancedChat.Views.LoginPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid KeyUp="GridKeyUp">
<Grid.RowDefinitions>
<RowDefinition Height="0.15*" />
<RowDefinition Height="0.85*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Background="{ThemeResource SystemAccentColorLight3}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Style="{ThemeResource HeaderTextBlockStyle}" Text="Login Form" />
</Border>
<StackPanel Grid.Row="1" VerticalAlignment="Center">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
<TextBlock Text="Identity :" />
<TextBox x:Name="Identity" Width="350" MinWidth="350" MaxWidth="350" Text="sip:" />
</StackPanel>
<StackPanel Margin="0,10,0,0" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
<TextBlock Text="Password :" />
<PasswordBox x:Name="Password" Width="350" MinWidth="350" MaxWidth="350" PlaceholderText="myPasswd" />
</StackPanel>
<Button x:Name="LogIn" Click="LogInClick" Content="Login" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10,0,0" />
<TextBlock x:Name="RegistrationText" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10,0,0" />
</StackPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using _07_AdvancedChat.Service;
using Linphone;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
namespace _07_AdvancedChat.Views
{
/// <summary>
/// A really simple app for a first Login with LinphoneSDK x UWP
/// </summary>
public sealed partial class LoginPage : Page
{
private CoreService CoreService { get; } = CoreService.Instance;
public LoginPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
CoreService.AddOnAccountRegistrationStateChangedDelegate(OnAccountRegistrationStateChanged);
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
CoreService.RemoveOnAccountRegistrationStateChangedDelegate(OnAccountRegistrationStateChanged);
base.OnNavigatingFrom(e);
}
/// <summary>
/// Called when you click on the "Login" button.
/// </summary>
private void LogInClick(object sender, RoutedEventArgs e)
{
if (LogIn.IsEnabled)
{
LogIn.IsEnabled = false;
CoreService.LogIn(Identity.Text, Password.Password);
}
}
/// <summary>
/// Called when a key is pressed and released on the login page.
/// If you pressed "Enter", simulate a login click.
/// </summary>
private void GridKeyUp(object sender, KeyRoutedEventArgs e)
{
if (VirtualKey.Enter.Equals(e.Key))
{
LogInClick(null, null);
}
}
/// <summary>
/// This method is called every time the RegistrationState is updated by background core's actions.
/// In this example we use this to update the GUI.
/// </summary>
private void OnAccountRegistrationStateChanged(Core core, Account account, RegistrationState state, string message)
{
RegistrationText.Text = "Your registration state is : " + state.ToString();
switch (state)
{
case RegistrationState.Cleared:
case RegistrationState.None:
CoreService.ClearCoreAfterLogOut();
LogIn.IsEnabled = true;
break;
case RegistrationState.Ok:
LogIn.IsEnabled = false;
this.Frame.Navigate(typeof(NavigationRoot));
break;
case RegistrationState.Progress:
LogIn.IsEnabled = false;
break;
case RegistrationState.Failed:
LogIn.IsEnabled = true;
break;
default:
break;
}
}
}
}

View File

@@ -0,0 +1,43 @@
<Page
x:Class="_07_AdvancedChat.Views.NavigationRoot"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded">
<Grid x:Name="NavRootGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<NavigationView
x:Name="navview"
AlwaysShowHeader="False"
ItemInvoked="Navview_ItemInvoked"
PaneDisplayMode="Top"
IsBackButtonVisible="Collapsed">
<NavigationView.MenuItems>
<NavigationViewItem Content="Calls" IsSelected="True">
<NavigationViewItem.Icon>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xF715;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem>
<NavigationViewItem.Icon>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE8F2;" />
</NavigationViewItem.Icon>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Chats" />
<Border x:Name="NewMessageCountBorder" BorderThickness="1" BorderBrush="Red" CornerRadius="10" Margin="5,0,0,0" Padding="3,0,3,0">
<TextBlock x:Name="NewMessageCount" Text="0" />
</Border>
</StackPanel>
</NavigationViewItem>
</NavigationView.MenuItems>
<NavigationView.PaneFooter>
<NavigationViewItem Content="Sign out" Tapped="SignOut_Tapped">
<NavigationViewItem.Icon>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xF3B1;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
</NavigationView.PaneFooter>
<Frame x:Name="AppNavFrame" Navigated="AppNavFrame_Navigated" />
</NavigationView>
</Grid>
</Page>

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using _07_AdvancedChat.Service;
using Linphone;
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
namespace _07_AdvancedChat.Views
{
/// <summary>
/// A really simple app for a first Login with LinphoneSDK x UWP
/// </summary>
public sealed partial class NavigationRoot : Page
{
private CoreService CoreService { get; } = CoreService.Instance;
private NavigationService NavigationService { get; } = NavigationService.Instance;
private bool hasLoadedPreviously;
public NavigationRoot()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
this.CoreService.AddOnOnMessageReceivedDelegate(OnMessageReveive);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
this.CoreService.RemoveOnOnMessageReceivedDelegate(OnMessageReveive);
base.OnNavigatedFrom(e);
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
// Only do an inital navigate the first time the page loads
// when we switch out of compactoverloadmode this will fire but we don't want to navigate because
// there is already a page loaded
if (!hasLoadedPreviously)
{
AppNavFrame.Navigate(typeof(CallsPage));
UpdateUnreadMessageCount();
hasLoadedPreviously = true;
NavigationService.CurrentNavigationRoot = this;
}
}
private void AppNavFrame_Navigated(object sender, NavigationEventArgs e)
{
switch (e.SourcePageType)
{
case Type c when e.SourcePageType == typeof(CallsPage):
((NavigationViewItem)navview.MenuItems[0]).IsSelected = true;
break;
case Type c when e.SourcePageType == typeof(ChatsPage):
((NavigationViewItem)navview.MenuItems[1]).IsSelected = true;
break;
}
}
private async void Navview_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
if (args.IsSettingsInvoked)
{
ContentDialog noSettingsDialog = new ContentDialog
{
Title = "No settings",
Content = "There is no settings in this little app",
CloseButtonText = "OK"
};
ContentDialogResult result = await noSettingsDialog.ShowAsync();
return;
}
string invokedItemValue = args.InvokedItem as string;
if (invokedItemValue != null && invokedItemValue.Contains("Calls"))
{
AppNavFrame.Navigate(typeof(CallsPage));
}
else
{
AppNavFrame.Navigate(typeof(ChatsPage));
}
}
private void SignOut_Tapped(object sender, TappedRoutedEventArgs e)
{
DisplaySignOutDialog();
}
private async void DisplaySignOutDialog()
{
ContentDialog signOutDialog = new ContentDialog
{
Title = "Sign out ?",
Content = "All your current calls and actions will be canceled, are you sure to continue ?",
PrimaryButtonText = "Sign out",
CloseButtonText = "Cancel"
};
ContentDialogResult result = await signOutDialog.ShowAsync();
if (result == ContentDialogResult.Primary)
{
CoreService.Core.TerminateAllCalls();
CoreService.LogOut();
this.Frame.Navigate(typeof(LoginPage));
}
}
private void OnMessageReveive(Core core, ChatRoom chatRoom, ChatMessage message)
{
UpdateUnreadMessageCount();
}
public void UpdateUnreadMessageCount()
{
if (CoreService.Core.UnreadChatMessageCountFromActiveLocals > 0)
{
NewMessageCount.Text = "" + CoreService.Core.UnreadChatMessageCountFromActiveLocals;
NewMessageCountBorder.Visibility = Visibility.Visible;
}
else
{
NewMessageCountBorder.Visibility = Visibility.Collapsed;
}
}
}
}