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="_04_BasicChat.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 _04_BasicChat.Service;
using Linphone;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace _04_BasicChat.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,41 @@
<Page
x:Class="_04_BasicChat.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="auto" />
<RowDefinition Height="0.75*" />
<RowDefinition Height="0.15*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock x:Name="ChatHeaderText" Text="Your conversation with : " Style="{ThemeResource HeaderTextBlockStyle}" />
</StackPanel>
<Grid Grid.Row="1" 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="2" x:Name="MessagesScroll">
<StackPanel Padding="10"
x:Name="MessagesList"
Orientation="Vertical"
VerticalAlignment="Bottom">
</StackPanel>
</ScrollViewer>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.80*" />
<ColumnDefinition Width="0.20*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" x:Name="OutgoingMessageText" Text="" AcceptsReturn="True" TextWrapping="Wrap" />
<Button Grid.Column="1" x:Name="OutgoingMessageButton" Click="OutgoingMessageButton_Click" Content="Send" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,151 @@
/*
* 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 _04_BasicChat.Service;
using Linphone;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace _04_BasicChat.Views
{
public sealed partial class ChatPage : Page
{
private NavigationService NavigationService { get; } = NavigationService.Instance;
private ChatRoom ChatRoom;
public ChatPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ChatRoom = ((ChatRoom)e.Parameter);
// The ChatRoom also offers to register to some callbacks.
// One of them is OnMessageReceived, like the one we used
// on the core (Core.Listener.OnMessageReceived) but this one
// is triggered only when the message received is part of this
// ChatRoom.
ChatRoom.Listener.OnMessageReceived += OnMessageReceived;
// The method GetHistory get all the ChatMessage you have
// in your local database for this ChatRoom. GetHistory(0)
// means everything but you can specify a max number of messages.
foreach (ChatMessage chatMessage in ChatRoom.GetHistory(0))
{
// See AddMessage(ChatMessage chatMessage) to see how we display messages
AddMessage(chatMessage);
}
// Mark all the messages in th ChatRoom as read, if some messages
// weren't, this will trigger some read notifications to the remote.
ChatRoom.MarkAsRead();
// Only here to update display of unread message count on parent frames.
// See NavigationRoot.UpdateUnreadMessageCount() to see how to get a
// global unread message count.
NavigationService.CurrentNavigationRoot.UpdateUnreadMessageCount();
NavigationService.CurrentChatspage.UpdateChatRooms();
// We can find all the info from the peer in the PeerAddress attribute
// of a ChatRoom object.
ChatHeaderText.Text += ChatRoom.PeerAddress.Username;
PeerUsername.Text += ChatRoom.PeerAddress.Username;
// And yours in LocalAddress.
YourUsername.Text += ChatRoom.LocalAddress.Username;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// Don't forget to unregister delegate to avoid memory leak
ChatRoom.Listener = null;
}
/// <summary>
/// Delegate method called every time a message is received in this chat room.
/// </summary>
private void OnMessageReceived(ChatRoom chatRoom, ChatMessage message)
{
if (ChatRoom != null)
{
AddMessage(message);
chatRoom.MarkAsRead();
}
}
private void AddMessage(ChatMessage chatMessage)
{
TextBlock textBlock = new TextBlock();
// You can find a lot of information on a ChatMessage object.
// Here we used the IsOutgoing info to choose on each side
// of the frame the message should be displayed.
if (chatMessage.IsOutgoing)
{
textBlock.HorizontalAlignment = HorizontalAlignment.Right;
}
else
{
textBlock.HorizontalAlignment = HorizontalAlignment.Left;
}
// You can see we take the first element of the Contents list of our ChatMessage. To keep
// it simple we assume that we only send simple text message, we will talk more about multipart
// messages and other types of messagse in the next step.
// For now we only handle chat messages with one content, so we can find our text in
// chatMessage.Contents.First().Utf8Text.
// We used ["" +] because if the message is a file transfer for example the Utf8Text can be null.
textBlock.Text = "" + chatMessage.Contents.First().Utf8Text;
MessagesList.Children.Add(textBlock);
ScrollToBottom();
}
private void ScrollToBottom()
{
MessagesScroll.UpdateLayout();
MessagesScroll.ChangeView(1, MessagesScroll.ExtentHeight, 1);
}
/// <summary>
/// Method called when the "Send" button is clicked
/// </summary>
private void OutgoingMessageButton_Click(object sender, RoutedEventArgs e)
{
if (ChatRoom != null && OutgoingMessageText.Text != null && OutgoingMessageText.Text.Length > 0)
{
// We use the ChatRoom to create a new ChatMessage object. Here we used
// the method CreateMessage(string message) to create a text message.
ChatMessage chatMessage = ChatRoom.CreateMessage(OutgoingMessageText.Text);
// And simply call the Send() method to send the message.
chatMessage.Send();
AddMessage(chatMessage);
}
OutgoingMessageText.Text = "";
}
}
}

View File

@@ -0,0 +1,39 @@
<Page
x:Class="_04_BasicChat.Views.ChatsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:linphone="using:Linphone"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<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 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 PeerAddress.AsString()}" 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,165 @@
/*
* 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 _04_BasicChat.Service;
using Linphone;
using System;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace _04_BasicChat.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);
// We just do this so we can update the list from other pages.
NavigationService.CurrentChatspage = this;
// Find and update the chat rooms list, see UpdateChatRooms
UpdateChatRooms();
// You are now familiar with those kinds of callback register.
// Here we want to update the list every time a message is
// received (list order and unread message count, see ChatsPage.xaml)
// or sent (list order)
CoreService.AddOnOnMessageReceivedDelegate(OnMessageReceiveOrSent);
CoreService.AddOnMessageSentDelegate(OnMessageReceiveOrSent);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
NavigationService.CurrentChatspage = null;
// You need to unregister delegate to allow the garbage collector to
// collect this instance when you navigate away.
CoreService.RemoveOnOnMessageReceivedDelegate(OnMessageReceiveOrSent);
CoreService.RemoveOnMessageSentDelegate(OnMessageReceiveOrSent);
base.OnNavigatedFrom(e);
}
/// <summary>
/// Method called too update the list every time a message is received or sent.
/// </summary>
private void OnMessageReceiveOrSent(Core core, ChatRoom chatRoom, ChatMessage message) => UpdateChatRooms();
public void UpdateChatRooms()
{
ChatRoom selectedChatRoom = (ChatRoom)ChatRoomsLV.SelectedItem;
ChatRoomsLV.Items.Clear();
// In the ChatRooms list attribute you can find every ChatRooms linked
// to your user. The list is ordered by ChatRoom last activity date
// (most recent first).
// You can see in Chats.xaml that we only use the properties
// UnreadMessagesCount and PeerAdress to display our chat rooms.
// In further steps we will do more.
foreach (ChatRoom chatRoom in CoreService.Core.ChatRooms)
{
// Here we use the HistorySize attribute to display only
// ChatRooms were at least one message was exchange.
if (chatRoom.HistorySize > 0)
{
ChatRoomsLV.Items.Add(chatRoom);
if (selectedChatRoom == chatRoom)
{
ChatRoomsLV.SelectedItem = chatRoom;
}
}
}
}
/// <summary>
/// Method called when any item of the chat rooms ListView is clicked.
/// </summary>
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 InputTextDialogAsync("Enter peer sip address");
if (!String.IsNullOrWhiteSpace(peerSipAddress))
{
// We create a new ChatRoom with the address the user gave us.
// See CoreService.CreateOrGetChatRoom(string sipAddress) for more info
ChatRoom newChatRoom = CoreService.CreateOrGetChatRoom(peerSipAddress);
if (newChatRoom != null)
{
// If the ChatRoom creation succeed render/navigate to a ChatPage in the inner
// frame of the ChatsPage.
// See ChatPage.xaml.cs to understand how to get message history and how to send/receive
// and display new messages.
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();
}
}
}
/// <summary>
/// Small utility method to display a dialog with an input text
/// </summary>
private async Task<string> InputTextDialogAsync(string title)
{
TextBox inputTextBox = new TextBox
{
AcceptsReturn = false,
Height = 32
};
ContentDialog dialog = new ContentDialog
{
Content = inputTextBox,
Title = title,
IsSecondaryButtonEnabled = true,
PrimaryButtonText = "OK",
SecondaryButtonText = "Cancel"
};
if (await dialog.ShowAsync() == ContentDialogResult.Primary)
return inputTextBox.Text;
else
return "";
}
}
}

View File

@@ -0,0 +1,34 @@
<Page
x:Class="_04_BasicChat.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 _04_BasicChat.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 _04_BasicChat.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="_04_BasicChat.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,158 @@
/*
* 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 _04_BasicChat.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 _04_BasicChat.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()
{
// The property UnreadChatMessageCountFromActiveLocals return the total
// number of unread messages in all the chat rooms off all connected accounts
// on the device. In the tutorial we only allow one account at a time, so
// you get the global unread message count for your account.
if (CoreService.Core.UnreadChatMessageCountFromActiveLocals > 0)
{
NewMessageCount.Text = "" + CoreService.Core.UnreadChatMessageCountFromActiveLocals;
NewMessageCountBorder.Visibility = Visibility.Visible;
}
else
{
NewMessageCountBorder.Visibility = Visibility.Collapsed;
}
}
}
}