Add new VideoConference module for muting mic/cam (#11798)

* add new VideoConference module for muting mic/cam

Co-authored-by: PrzemyslawTusinski <61138537+PrzemyslawTusinski@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
Andrey Nekrasov
2021-06-29 13:06:12 +03:00
committed by GitHub
parent e450669663
commit 4e23832d52
116 changed files with 7425 additions and 81 deletions

View File

@@ -80,6 +80,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private bool videoConference = true;
[JsonPropertyName("Video Conference")]
public bool VideoConference
{
get => this.videoConference;
set
{
if (this.videoConference != value)
{
LogTelemetryEvent(value);
this.videoConference = value;
}
}
}
private bool powerRename = true;
public bool PowerRename

View File

@@ -58,4 +58,11 @@
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Windows.Forms.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class SndVideoConferenceSettings
{
[JsonPropertyName("Video Conference")]
public VideoConferenceSettings VideoConference { get; set; }
public SndVideoConferenceSettings(VideoConferenceSettings settings)
{
VideoConference = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -29,5 +30,15 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
return JsonSerializer.Serialize(this);
}
public static StringProperty ToStringProperty(string v)
{
return new StringProperty(v);
}
public static implicit operator StringProperty(string v)
{
return new StringProperty(v);
}
}
}

View File

@@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class VideoConferenceConfigProperties
{
public VideoConferenceConfigProperties()
{
this.MuteCameraAndMicrophoneHotkey = new KeyboardKeysProperty(
new HotkeySettings()
{
Win = true,
Ctrl = false,
Alt = false,
Shift = false,
Key = "N",
Code = 78,
});
this.MuteMicrophoneHotkey = new KeyboardKeysProperty(
new HotkeySettings()
{
Win = true,
Ctrl = false,
Alt = false,
Shift = true,
Key = "A",
Code = 65,
});
this.MuteCameraHotkey = new KeyboardKeysProperty(
new HotkeySettings()
{
Win = true,
Ctrl = false,
Alt = false,
Shift = true,
Key = "O",
Code = 79,
});
this.HideToolbarWhenUnmuted = new BoolProperty(true);
}
[JsonPropertyName("mute_camera_and_microphone_hotkey")]
public KeyboardKeysProperty MuteCameraAndMicrophoneHotkey { get; set; }
[JsonPropertyName("mute_microphone_hotkey")]
public KeyboardKeysProperty MuteMicrophoneHotkey { get; set; }
[JsonPropertyName("mute_camera_hotkey")]
public KeyboardKeysProperty MuteCameraHotkey { get; set; }
[JsonPropertyName("selected_camera")]
public StringProperty SelectedCamera { get; set; } = string.Empty;
[JsonPropertyName("selected_mic")]
public StringProperty SelectedMicrophone { get; set; } = string.Empty;
[JsonPropertyName("toolbar_position")]
public StringProperty ToolbarPosition { get; set; } = "Top right corner";
[JsonPropertyName("toolbar_monitor")]
public StringProperty ToolbarMonitor { get; set; } = "Main monitor";
[JsonPropertyName("camera_overlay_image_path")]
public StringProperty CameraOverlayImagePath { get; set; } = string.Empty;
[JsonPropertyName("theme")]
public StringProperty Theme { get; set; }
[JsonPropertyName("hide_toolbar_when_unmuted")]
public BoolProperty HideToolbarWhenUnmuted { get; set; }
// converts the current to a json string.
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class VideoConferenceSettings : BasePTModuleSettings, ISettingsConfig
{
public VideoConferenceSettings()
{
Version = "1";
Name = "Video Conference";
Properties = new VideoConferenceConfigProperties();
}
[JsonPropertyName("properties")]
public VideoConferenceConfigProperties Properties { get; set; }
public string GetModuleName()
{
return Name;
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class VideoConferenceSettingsIPCMessage
{
[JsonPropertyName("powertoys")]
public SndVideoConferenceSettings Powertoys { get; set; }
public VideoConferenceSettingsIPCMessage()
{
}
public VideoConferenceSettingsIPCMessage(SndVideoConferenceSettings settings)
{
this.Powertoys = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -0,0 +1,432 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class VideoConferenceViewModel : Observable
{
private readonly ISettingsUtils _settingsUtils;
private VideoConferenceSettings Settings { get; set; }
private GeneralSettings GeneralSettingsConfig { get; set; }
private const string ModuleName = "Video Conference";
private Func<string, int> SendConfigMSG { get; }
private string _settingsConfigFileFolder = string.Empty;
public VideoConferenceViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, string configFileSubfolder = "")
{
if (settingsRepository == null)
{
throw new ArgumentNullException(nameof(settingsRepository));
}
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
SendConfigMSG = ipcMSGCallBackFunc;
_settingsConfigFileFolder = configFileSubfolder;
try
{
Settings = _settingsUtils.GetSettings<VideoConferenceSettings>(GetSettingsSubPath());
}
#pragma warning disable CA1031 // Do not catch general exception types
catch
#pragma warning restore CA1031 // Do not catch general exception types
{
Settings = new VideoConferenceSettings();
_settingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath());
}
CameraNames = interop.CommonManaged.GetAllVideoCaptureDeviceNames();
MicrophoneNames = interop.CommonManaged.GetAllActiveMicrophoneDeviceNames();
MicrophoneNames.Insert(0, "[All]");
var shouldSaveSettings = false;
if (string.IsNullOrEmpty(Settings.Properties.SelectedCamera.Value) && CameraNames.Count != 0)
{
_selectedCameraIndex = 0;
Settings.Properties.SelectedCamera.Value = CameraNames[0];
shouldSaveSettings = true;
}
else
{
_selectedCameraIndex = CameraNames.FindIndex(name => name == Settings.Properties.SelectedCamera.Value);
}
if (string.IsNullOrEmpty(Settings.Properties.SelectedMicrophone.Value))
{
_selectedMicrophoneIndex = 0;
Settings.Properties.SelectedMicrophone.Value = MicrophoneNames[0];
shouldSaveSettings = true;
}
else
{
_selectedMicrophoneIndex = MicrophoneNames.FindIndex(name => name == Settings.Properties.SelectedMicrophone.Value);
}
_isEnabled = GeneralSettingsConfig.Enabled.VideoConference;
_cameraAndMicrophoneMuteHotkey = Settings.Properties.MuteCameraAndMicrophoneHotkey.Value;
_mirophoneMuteHotkey = Settings.Properties.MuteMicrophoneHotkey.Value;
_cameraMuteHotkey = Settings.Properties.MuteCameraHotkey.Value;
CameraImageOverlayPath = Settings.Properties.CameraOverlayImagePath.Value;
SelectOverlayImage = new ButtonClickCommand(SelectOverlayImageAction);
ClearOverlayImage = new ButtonClickCommand(ClearOverlayImageAction);
_hideToolbarWhenUnmuted = Settings.Properties.HideToolbarWhenUnmuted.Value;
switch (Settings.Properties.ToolbarPosition.Value)
{
case "Top left corner":
_toolbarPositionIndex = 0;
break;
case "Top center":
_toolbarPositionIndex = 1;
break;
case "Top right corner":
_toolbarPositionIndex = 2;
break;
case "Bottom left corner":
_toolbarPositionIndex = 3;
break;
case "Bottom center":
_toolbarPositionIndex = 4;
break;
case "Bottom right corner":
_toolbarPositionIndex = 5;
break;
}
switch (Settings.Properties.ToolbarMonitor.Value)
{
case "Main monitor":
_toolbarMonitorIndex = 0;
break;
case "All monitors":
_toolbarMonitorIndex = 1;
break;
}
if (shouldSaveSettings)
{
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
}
private bool _isEnabled;
private int _toolbarPositionIndex;
private int _toolbarMonitorIndex;
private HotkeySettings _cameraAndMicrophoneMuteHotkey;
private HotkeySettings _mirophoneMuteHotkey;
private HotkeySettings _cameraMuteHotkey;
private int _selectedCameraIndex = -1;
private int _selectedMicrophoneIndex;
private bool _hideToolbarWhenUnmuted;
public List<string> CameraNames { get; }
public List<string> MicrophoneNames { get; }
public string CameraImageOverlayPath { get; set; }
public ButtonClickCommand SelectOverlayImage { get; set; }
public ButtonClickCommand ClearOverlayImage { get; set; }
private void ClearOverlayImageAction()
{
CameraImageOverlayPath = string.Empty;
Settings.Properties.CameraOverlayImagePath = string.Empty;
RaisePropertyChanged(nameof(CameraImageOverlayPath));
}
private void SelectOverlayImageAction()
{
try
{
string pickedImage = null;
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "Image Files (*.jpeg;*.jpg;*.png)|*.jpeg;*.jpg;*.png";
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
pickedImage = openFileDialog.FileName;
}
}
if (pickedImage != null)
{
CameraImageOverlayPath = pickedImage;
Settings.Properties.CameraOverlayImagePath = pickedImage;
RaisePropertyChanged(nameof(CameraImageOverlayPath));
}
}
#pragma warning disable CA1031 // Do not catch general exception types
catch
#pragma warning restore CA1031 // Do not catch general exception types
{
}
}
public int SelectedCameraIndex
{
get
{
return _selectedCameraIndex;
}
set
{
if (_selectedCameraIndex != value)
{
_selectedCameraIndex = value;
if (_selectedCameraIndex >= 0 && _selectedCameraIndex < CameraNames.Count)
{
Settings.Properties.SelectedCamera.Value = CameraNames[_selectedCameraIndex];
RaisePropertyChanged();
}
}
}
}
public int SelectedMicrophoneIndex
{
get
{
return _selectedMicrophoneIndex;
}
set
{
if (_selectedMicrophoneIndex != value)
{
_selectedMicrophoneIndex = value;
if (_selectedMicrophoneIndex >= 0 && _selectedMicrophoneIndex < MicrophoneNames.Count)
{
Settings.Properties.SelectedMicrophone.Value = MicrophoneNames[_selectedMicrophoneIndex];
RaisePropertyChanged();
}
}
}
}
public bool IsEnabled
{
get
{
return _isEnabled;
}
set
{
if (value != _isEnabled)
{
_isEnabled = value;
GeneralSettingsConfig.Enabled.VideoConference = value;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(snd.ToString());
OnPropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsElevated
{
get
{
return GeneralSettingsConfig.IsElevated;
}
}
public HotkeySettings CameraAndMicrophoneMuteHotkey
{
get
{
return _cameraAndMicrophoneMuteHotkey;
}
set
{
if (value != _cameraAndMicrophoneMuteHotkey)
{
_cameraAndMicrophoneMuteHotkey = value;
Settings.Properties.MuteCameraAndMicrophoneHotkey.Value = value;
RaisePropertyChanged(nameof(CameraAndMicrophoneMuteHotkey));
}
}
}
public HotkeySettings MicrophoneMuteHotkey
{
get
{
return _mirophoneMuteHotkey;
}
set
{
if (value != _mirophoneMuteHotkey)
{
_mirophoneMuteHotkey = value;
Settings.Properties.MuteMicrophoneHotkey.Value = value;
RaisePropertyChanged(nameof(MicrophoneMuteHotkey));
}
}
}
public HotkeySettings CameraMuteHotkey
{
get
{
return _cameraMuteHotkey;
}
set
{
if (value != _cameraMuteHotkey)
{
_cameraMuteHotkey = value;
Settings.Properties.MuteCameraHotkey.Value = value;
RaisePropertyChanged(nameof(CameraMuteHotkey));
}
}
}
public int ToolbarPostionIndex
{
get
{
return _toolbarPositionIndex;
}
set
{
if (_toolbarPositionIndex != value)
{
_toolbarPositionIndex = value;
switch (_toolbarPositionIndex)
{
case 0:
Settings.Properties.ToolbarPosition.Value = "Top left corner";
break;
case 1:
Settings.Properties.ToolbarPosition.Value = "Top center";
break;
case 2:
Settings.Properties.ToolbarPosition.Value = "Top right corner";
break;
case 3:
Settings.Properties.ToolbarPosition.Value = "Bottom left corner";
break;
case 4:
Settings.Properties.ToolbarPosition.Value = "Bottom center";
break;
case 5:
Settings.Properties.ToolbarPosition.Value = "Bottom right corner";
break;
}
RaisePropertyChanged(nameof(ToolbarPostionIndex));
}
}
}
public int ToolbarMonitorIndex
{
get
{
return _toolbarMonitorIndex;
}
set
{
if (_toolbarMonitorIndex != value)
{
_toolbarMonitorIndex = value;
switch (_toolbarMonitorIndex)
{
case 0:
Settings.Properties.ToolbarMonitor.Value = "Main monitor";
break;
case 1:
Settings.Properties.ToolbarMonitor.Value = "All monitors";
break;
}
RaisePropertyChanged(nameof(ToolbarMonitorIndex));
}
}
}
public bool HideToolbarWhenUnmuted
{
get
{
return _hideToolbarWhenUnmuted;
}
set
{
if (value != _hideToolbarWhenUnmuted)
{
_hideToolbarWhenUnmuted = value;
Settings.Properties.HideToolbarWhenUnmuted.Value = value;
RaisePropertyChanged(nameof(HideToolbarWhenUnmuted));
}
}
}
public string GetSettingsSubPath()
{
return _settingsConfigFileFolder + "\\" + ModuleName;
}
#pragma warning disable CA1030 // Use events where appropriate
public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
#pragma warning restore CA1030 // Use events where appropriate
{
OnPropertyChanged(propertyName);
SndVideoConferenceSettings outsettings = new SndVideoConferenceSettings(Settings);
SndModuleSettings<SndVideoConferenceSettings> ipcMessage = new SndModuleSettings<SndVideoConferenceSettings>(outsettings);
SendConfigMSG(ipcMessage.ToJsonString());
}
}
[ComImport]
[Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInitializeWithWindow
{
void Initialize(IntPtr hwnd);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -199,6 +199,9 @@
<Compile Include="Views\ShortcutGuidePage.xaml.cs">
<DependentUpon>ShortcutGuidePage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\VideoConference.xaml.cs">
<DependentUpon>VideoConference.xaml</DependentUpon>
</Compile>
<Compile Include="Views\VisibleIfNotEmpty.cs" />
</ItemGroup>
<ItemGroup>
@@ -240,6 +243,7 @@
<Content Include="Assets\Modules\PowerRename.png" />
<Content Include="Assets\Modules\PT.png" />
<Content Include="Assets\Modules\ShortcutGuide.png" />
<Content Include="Assets\Modules\VideoConference.png" />
<Content Include="Assets\SplashScreen.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
@@ -428,6 +432,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\VideoConference.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\codeAnalysis\StyleCop.json">

View File

@@ -117,6 +117,98 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Shell_VideoConference.Content" xml:space="preserve">
<value>Video Conference Mute</value>
<comment>Navigation view item name for Video Conference</comment>
</data>
<data name="VideoConference_Enable.Header" xml:space="preserve">
<value>Enable Video Conference</value>
</data>
<data name="VideoConference_Description.Text" xml:space="preserve">
<value>Video Conference Mute is a quick and easy way to do an global "mute" of both your microphone and webcam.
Disabling this module or closing PowerToys will unmute the microphone and camera.</value>
</data>
<data name="VideoConference_CameraAndMicrophoneMuteHotkeyControl_Header.Header" xml:space="preserve">
<value>Mute camera and microphone</value>
</data>
<data name="VideoConference_MicrophoneMuteHotkeyControl_Header.Header" xml:space="preserve">
<value>Mute microphone</value>
</data>
<data name="VideoConference_CameraMuteHotkeyControl_Header.Header" xml:space="preserve">
<value>Mute camera</value>
</data>
<data name="VideoConference_SelectedCamera.Header" xml:space="preserve">
<value>Selected camera</value>
</data>
<data name="VideoConference_SelectedMicrophone.Header" xml:space="preserve">
<value>Selected microphone</value>
</data>
<data name="VideoConference_CameraOverlayImagePathHeader.Text" xml:space="preserve">
<value>Camera overlay image</value>
</data>
<data name="VideoConference_ToolbarPosition.Header" xml:space="preserve">
<value>Toolbar position</value>
</data>
<data name="VideoConference_ToolbarPosition_TopCenter.Content" xml:space="preserve">
<value>Top center</value>
</data>
<data name="VideoConference_ToolbarPosition_TopLeftCorner.Content" xml:space="preserve">
<value>Top left corner</value>
</data>
<data name="VideoConference_ToolbarPosition_TopRightCorner.Content" xml:space="preserve">
<value>Top right corner</value>
</data>
<data name="VideoConference_ToolbarPosition_BottomLeftCorner.Content" xml:space="preserve">
<value>Bottom left corner</value>
</data>
<data name="VideoConference_ToolbarPosition_BottomCenter.Content" xml:space="preserve">
<value>Bottom center</value>
</data>
<data name="VideoConference_ToolbarPosition_BottomRightCorner.Content" xml:space="preserve">
<value>Bottom right corner</value>
</data>
<data name="VideoConference_ToolbarMonitor.Header" xml:space="preserve">
<value>Show toolbar on</value>
</data>
<data name="VideoConference_ToolbarMonitor_Main.Content" xml:space="preserve">
<value>Main monitor</value>
</data>
<data name="VideoConference_ToolbarMonitor_UnderCursor.Content" xml:space="preserve">
<value>Monitor under cursor</value>
</data>
<data name="VideoConference_ToolbarMonitor_ActiveWindow.Content" xml:space="preserve">
<value>Active window monitor</value>
</data>
<data name="VideoConference_ToolbarMonitor_All.Content" xml:space="preserve">
<value>All monitors</value>
</data>
<data name="VideoConference_HideToolbarWhenUnmuted.Content" xml:space="preserve">
<value>Hide toolbar when both camera and microphone are unmuted</value>
</data>
<data name="About_VideoConference.Text" xml:space="preserve">
<value>About Video Conference</value>
</data>
<data name="VideoConference_Camera.Text" xml:space="preserve">
<value>Camera</value>
</data>
<data name="VideoConference_Microphone.Text" xml:space="preserve">
<value>Microphone</value>
</data>
<data name="VideoConference_Toolbar.Text" xml:space="preserve">
<value>Toolbar</value>
</data>
<data name="VideoConference_Shortcuts.Text" xml:space="preserve">
<value>Shortcuts</value>
</data>
<data name="VideoConference_CameraOverlayImageAlt.AutomationProperties.Name" xml:space="preserve">
<value>Camera overlay image preview</value>
</data>
<data name="VideoConference_CameraOverlayImageBrowse.Content" xml:space="preserve">
<value>Browse</value>
</data>
<data name="VideoConference_CameraOverlayImageClear.Content" xml:space="preserve">
<value>Clear</value>
</data>
<data name="Shell_General.Content" xml:space="preserve">
<value>General</value>
<comment>Navigation view item name for General</comment>
@@ -948,6 +1040,10 @@
<value>https://aka.ms/PowerToysOverview_ShortcutGuide</value>
<comment>URL. Do not loc</comment>
</data>
<data name="VideoConference_ImageHyperlinkToDocs.NavigateUri" xml:space="preserve">
<value>https://aka.ms/PowerToysOverview_VideoConference</value>
<comment>URL. Do not loc</comment>
</data>
<data name="FancyZones_MoveWindowBasedOnRelativePosition.Content" xml:space="preserve">
<value>Win + Up/Down/Left/Right to move windows based on relative position</value>
</data>
@@ -1304,4 +1400,4 @@ From there, simply click on a Markdown file or SVG icon in the File Explorer and
<data name="General_DownloadAndInstall.Content" xml:space="preserve">
<value>Download and install</value>
</data>
</root>
</root>

View File

@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
@@ -36,6 +37,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
set { Set(ref isBackEnabled, value); }
}
public bool IsVideoConferenceBuild
{
get
{
return this != null && File.Exists("modules/VideoConference/VideoConferenceModule.dll");
}
}
public WinUI.NavigationViewItem Selected
{
get { return selected; }

View File

@@ -89,6 +89,14 @@
<FontIcon Glyph="&#xEDA7;"/>
</winui:NavigationViewItem.Icon>
</winui:NavigationViewItem>
<!--TODO(yuyoyuppe): uncomment when VCM should be enabled-->
<!--<winui:NavigationViewItem x:Uid="Shell_VideoConference" helpers:NavHelper.NavigateTo="views:VideoConferencePage" IsEnabled="{x:Bind ViewModel.IsVideoConferenceBuild, Mode=OneWay}">
<winui:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE714;"/>
</winui:NavigationViewItem.Icon>
</winui:NavigationViewItem>-->
</winui:NavigationView.MenuItems>
<i:Interaction.Behaviors>
<behaviors:NavigationViewHeaderBehavior

View File

@@ -0,0 +1,210 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.VideoConferencePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:CustomControls="using:Microsoft.PowerToys.Settings.UI.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid RowSpacing="{StaticResource DefaultRowSpacing}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideLayoutMinWidth}" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="SmallLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource SmallLayoutMinWidth}" />
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SidePanel.(Grid.Column)" Value="0"/>
<Setter Target="SidePanel.Width" Value="Auto"/>
<Setter Target="VideoConferenceView.(Grid.Row)" Value="1" />
<Setter Target="LinksPanel.(RelativePanel.RightOf)" Value="AboutImage"/>
<Setter Target="LinksPanel.(RelativePanel.AlignTopWith)" Value="AboutImage"/>
<Setter Target="AboutImage.Margin" Value="0,12,12,0"/>
<Setter Target="AboutTitle.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" x:Name="VideoConferenceView">
<ToggleSwitch x:Uid="VideoConference_Enable"
IsOn="{ Binding Mode=TwoWay, Path=IsEnabled}"
IsEnabled="{ Binding Mode=OneWay, Path=IsElevated }"
/>
<TextBlock x:Uid="VideoConference_Shortcuts"
Style="{StaticResource SettingsGroupTitleStyle}"
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}" />
<CustomControls:HotkeySettingsControl
x:Uid="VideoConference_CameraAndMicrophoneMuteHotkeyControl_Header"
Width="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
Keys="Win, Ctrl, Alt, Shift"
HotkeySettings="{x:Bind Path=ViewModel.CameraAndMicrophoneMuteHotkey, Mode=TwoWay}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"
/>
<CustomControls:HotkeySettingsControl
x:Uid="VideoConference_MicrophoneMuteHotkeyControl_Header"
Width="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
Keys="Win, Ctrl, Alt, Shift"
HotkeySettings="{x:Bind Path=ViewModel.MicrophoneMuteHotkey, Mode=TwoWay}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"
/>
<CustomControls:HotkeySettingsControl
x:Uid="VideoConference_CameraMuteHotkeyControl_Header"
Width="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
Keys="Win, Ctrl, Alt, Shift"
HotkeySettings="{x:Bind Path=ViewModel.CameraMuteHotkey, Mode=TwoWay}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"
/>
<TextBlock x:Uid="VideoConference_Microphone"
Style="{StaticResource SettingsGroupTitleStyle}"
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
<ComboBox x:Uid="VideoConference_SelectedMicrophone"
Width="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
SelectedIndex="{Binding Path=SelectedMicrophoneIndex, Mode=TwoWay}"
ItemsSource="{Binding MicrophoneNames, Mode=OneTime}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"/>
<TextBlock x:Uid="VideoConference_Camera"
Style="{StaticResource SettingsGroupTitleStyle}"
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
<ComboBox x:Uid="VideoConference_SelectedCamera"
Width="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
SelectedIndex="{Binding Path=SelectedCameraIndex, Mode=TwoWay}"
ItemsSource="{Binding CameraNames, Mode=OneTime}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"/>
<TextBlock x:Uid="VideoConference_CameraOverlayImagePathHeader"
Margin="{StaticResource SmallTopMargin}"/>
<Border CornerRadius="4"
HorizontalAlignment="Left"
Margin="{StaticResource XXSmallTopMargin}">
<Image Width="240"
x:Uid="VideoConference_CameraOverlayImageAlt"
ToolTipService.ToolTip="{Binding Mode=OneWay, Path=CameraImageOverlayPath}"
Source="{Binding Mode=OneWay, Path=CameraImageOverlayPath}"/>
</Border>
<StackPanel Orientation="Horizontal"
Padding="0"
Spacing="8"
Margin="{StaticResource SmallTopMargin}">
<Button Height="32"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"
x:Uid="VideoConference_CameraOverlayImageBrowse"
Command="{Binding Mode=OneWay, Path=SelectOverlayImage}"
HorizontalContentAlignment="Left"
HorizontalAlignment="Left" />
<Button IsEnabled="{Binding Mode=TwoWay, Path=IsEnabled}"
Height="32"
x:Uid="VideoConference_CameraOverlayImageClear"
Command="{Binding Mode=OneWay, Path=ClearOverlayImage}"
HorizontalAlignment="Left" />
</StackPanel>
<TextBlock x:Uid="VideoConference_Toolbar"
Style="{StaticResource SettingsGroupTitleStyle}"
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
<ComboBox x:Uid="VideoConference_ToolbarPosition"
MinWidth="240"
Margin="{StaticResource SmallTopMargin}"
SelectedIndex="{ Binding Mode=TwoWay, Path=ToolbarPostionIndex}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}">
<ComboBoxItem x:Uid="VideoConference_ToolbarPosition_TopLeftCorner"/>
<ComboBoxItem x:Uid="VideoConference_ToolbarPosition_TopCenter"/>
<ComboBoxItem x:Uid="VideoConference_ToolbarPosition_TopRightCorner"/>
<ComboBoxItem x:Uid="VideoConference_ToolbarPosition_BottomLeftCorner"/>
<ComboBoxItem x:Uid="VideoConference_ToolbarPosition_BottomCenter"/>
<ComboBoxItem x:Uid="VideoConference_ToolbarPosition_BottomRightCorner"/>
</ComboBox>
<ComboBox x:Uid="VideoConference_ToolbarMonitor"
MinWidth="240"
Margin="{StaticResource SmallTopMargin}"
SelectedIndex="{ Binding Mode=TwoWay, Path=ToolbarMonitorIndex}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}">
<ComboBoxItem x:Uid="VideoConference_ToolbarMonitor_Main"/>
<ComboBoxItem x:Uid="VideoConference_ToolbarMonitor_All"/>
</ComboBox>
<CheckBox x:Uid="VideoConference_HideToolbarWhenUnmuted"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.HideToolbarWhenUnmuted}"
Margin="{StaticResource SmallTopMargin}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
/>
</StackPanel>
<RelativePanel x:Name="SidePanel"
HorizontalAlignment="Left"
Width="{StaticResource SidePanelWidth}"
Grid.Column="1">
<StackPanel x:Name="DescriptionPanel">
<TextBlock x:Uid="About_VideoConference"
x:Name="AboutTitle"
Grid.ColumnSpan="2"
Style="{StaticResource SettingsGroupTitleStyle}"
Margin="{StaticResource XSmallBottomMargin}"/>
<TextBlock x:Uid="VideoConference_Description"
TextWrapping="Wrap"
Grid.Row="1" />
</StackPanel>
<Border x:Name="AboutImage"
CornerRadius="4"
Grid.Row="2"
MaxWidth="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopBottomMargin}"
RelativePanel.Below="DescriptionPanel">
<HyperlinkButton x:Uid="VideoConference_ImageHyperlinkToDocs">
<Image Source="ms-appx:///Assets/Modules/VideoConference.png" />
</HyperlinkButton>
</Border>
<StackPanel x:Name="LinksPanel"
Margin="0,1,0,0"
RelativePanel.Below="AboutImage"
Orientation="Vertical" >
<HyperlinkButton x:Uid="VideoConference_ImageHyperlinkToDocs">
<TextBlock x:Uid="Module_overview" />
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://aka.ms/powerToysGiveFeedback">
<TextBlock x:Uid="Give_Feedback" />
</HyperlinkButton>
</StackPanel>
</RelativePanel>
</Grid>
</Page>

View File

@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class VideoConferencePage : Page
{
private VideoConferenceViewModel ViewModel { get; set; }
public VideoConferencePage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new VideoConferenceViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
}
}