-
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
167 changed files
with
11,815 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
.idea/ | ||
.vs/ | ||
*.DotSettings | ||
Volumey/bin/ | ||
Volumey/obj/ | ||
Volumey.Tests/bin/ | ||
Volumey.Tests/obj/ | ||
Volumey.Package/bin/ | ||
Volumey.Package/obj/ | ||
Volumey.Package/AppPackages/ | ||
Volumey.Package/Volumey.Package.wapproj.user | ||
Volumey.Package/BundleArtifacts/ |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+547 Bytes
Volumey.Package/Assets/Square44x44Logo.targetsize-16_altform-lightunplated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+547 Bytes
Volumey.Package/Assets/Square44x44Logo.targetsize-16_altform-unplated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+6.94 KB
Volumey.Package/Assets/Square44x44Logo.targetsize-256_altform-lightunplated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+6.94 KB
Volumey.Package/Assets/Square44x44Logo.targetsize-256_altform-unplated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.5 KB
Volumey.Package/Assets/Square44x44Logo.targetsize-48_altform-lightunplated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.5 KB
Volumey.Package/Assets/Square44x44Logo.targetsize-48_altform-unplated.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
|
||
<Package | ||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" | ||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" | ||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" | ||
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" | ||
IgnorableNamespaces="uap rescap"> | ||
|
||
<Identity | ||
Name="58593StasG.Volumey" | ||
Publisher="CN=978C2FB1-8A3A-4D5E-BC79-3F2149147466" | ||
Version="1.1.0.0"/> | ||
|
||
<Properties> | ||
<DisplayName>Volumey</DisplayName> | ||
<PublisherDisplayName>StasG</PublisherDisplayName> | ||
<Logo>Assets\StoreLogo.png</Logo> | ||
</Properties> | ||
|
||
<Dependencies> | ||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0"/> | ||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0"/> | ||
</Dependencies> | ||
|
||
<Resources> | ||
<Resource Language="en"/> | ||
<Resource Language="ru"/> | ||
<Resource Language="de"/> | ||
<Resource Language="it"/> | ||
<Resource Language="fr"/> | ||
<Resource Language="es"/> | ||
<Resource Language="pt"/> | ||
<Resource Language="ja"/> | ||
<Resource Language="zh-Hans"/> | ||
<Resource Language="hi"/> | ||
</Resources> | ||
<Applications> | ||
<Application Id="App" | ||
Executable="$targetnametoken$.exe" | ||
EntryPoint="$targetentrypoint$"> | ||
<Extensions> | ||
<uap5:Extension Category="windows.startupTask"> | ||
<uap5:StartupTask | ||
TaskId="A86EAB47-B1CF-42FC-9DF8-FBBC90C21AA6" | ||
Enabled="true" | ||
DisplayName="Volumey"/> | ||
</uap5:Extension> | ||
</Extensions> | ||
<uap:VisualElements | ||
DisplayName="Volumey" | ||
BackgroundColor="transparent" | ||
Square150x150Logo="Assets\Square150x150Logo.png" | ||
Square44x44Logo="Assets\Square44x44Logo.png" Description="Volumey"> | ||
<uap:SplashScreen | ||
xmlns:a="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" | ||
BackgroundColor="transparent" | ||
Image="Assets\SplashScreen.png" | ||
a:Optional="true"/> | ||
<uap:DefaultTile Square71x71Logo="Assets\Square71x71Logo.png"> | ||
<uap:ShowNameOnTiles> | ||
<uap:ShowOn Tile="square150x150Logo"/> | ||
</uap:ShowNameOnTiles> | ||
</uap:DefaultTile> | ||
</uap:VisualElements> | ||
</Application> | ||
</Applications> | ||
|
||
<Capabilities> | ||
<rescap:Capability Name="runFullTrust"/> | ||
</Capabilities> | ||
</Package> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '15.0'"> | ||
<VisualStudioVersion>15.0</VisualStudioVersion> | ||
</PropertyGroup> | ||
<ItemGroup Label="ProjectConfigurations"> | ||
<ProjectConfiguration Include="Debug|x86"> | ||
<Configuration>Debug</Configuration> | ||
<Platform>x86</Platform> | ||
</ProjectConfiguration> | ||
<ProjectConfiguration Include="Release|x86"> | ||
<Configuration>Release</Configuration> | ||
<Platform>x86</Platform> | ||
</ProjectConfiguration> | ||
<ProjectConfiguration Include="Debug|x64"> | ||
<Configuration>Debug</Configuration> | ||
<Platform>x64</Platform> | ||
</ProjectConfiguration> | ||
<ProjectConfiguration Include="Release|x64"> | ||
<Configuration>Release</Configuration> | ||
<Platform>x64</Platform> | ||
</ProjectConfiguration> | ||
</ItemGroup> | ||
<PropertyGroup> | ||
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath> | ||
</PropertyGroup> | ||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" /> | ||
<PropertyGroup> | ||
<ProjectGuid>ad0f301c-ebf5-4929-a4c3-ef76ee46b56e</ProjectGuid> | ||
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion> | ||
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion> | ||
<DefaultLanguage>en</DefaultLanguage> | ||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled> | ||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile> | ||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm> | ||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision> | ||
<GenerateTestArtifacts>True</GenerateTestArtifacts> | ||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks> | ||
<AppxBundlePlatforms>x64</AppxBundlePlatforms> | ||
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled> | ||
<PublishTrimmed>true</PublishTrimmed> | ||
<EntryPointProjectUniqueName>..\Volumey\Volumey.csproj</EntryPointProjectUniqueName> | ||
<PackageCertificateThumbprint>66853249B21CD36389814FCA74FD03767E5EFB35</PackageCertificateThumbprint> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||
<AppxBundle>Never</AppxBundle> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'"> | ||
<AppxBundle>Never</AppxBundle> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||
<AppxBundle>Never</AppxBundle> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'"> | ||
<AppxBundle>Never</AppxBundle> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<AppxManifest Include="Package.appxmanifest"> | ||
<SubType>Designer</SubType> | ||
</AppxManifest> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\Volumey\Volumey.csproj"> | ||
<Project>{33547cae-0bd2-4a17-a47c-b02c58d37944}</Project> | ||
<Name>Volumey</Name> | ||
<SkipGetTargetFrameworkProperties>True</SkipGetTargetFrameworkProperties> | ||
</ProjectReference> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Content Include="Assets\SplashScreen.scale-100.png" /> | ||
<Content Include="Assets\SplashScreen.scale-200.png" /> | ||
<Content Include="Assets\SplashScreen.scale-400.png" /> | ||
<Content Include="Assets\Square150x150Logo.scale-100.png" /> | ||
<Content Include="Assets\Square150x150Logo.scale-200.png" /> | ||
<Content Include="Assets\Square150x150Logo.scale-400.png" /> | ||
<Content Include="Assets\Square44x44Logo.scale-100.png" /> | ||
<Content Include="Assets\Square44x44Logo.scale-200.png" /> | ||
<Content Include="Assets\Square44x44Logo.scale-400.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-16.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-16_altform-lightunplated.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-16_altform-unplated.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-256.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-256_altform-lightunplated.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-256_altform-unplated.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-48.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-48_altform-lightunplated.png" /> | ||
<Content Include="Assets\Square44x44Logo.targetsize-48_altform-unplated.png" /> | ||
<Content Include="Assets\Square71x71Logo.scale-100.png" /> | ||
<Content Include="Assets\Square71x71Logo.scale-200.png" /> | ||
<Content Include="Assets\Square71x71Logo.scale-400.png" /> | ||
<Content Include="Assets\StoreLogo.scale-100.png" /> | ||
<Content Include="Assets\StoreLogo.scale-200.png" /> | ||
<Content Include="Assets\StoreLogo.scale-400.png" /> | ||
<None Include="Package.StoreAssociation.xml" /> | ||
</ItemGroup> | ||
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" /> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System.Windows.Media.Imaging; | ||
using Moq; | ||
using Volumey.CoreAudioWrapper.Wrapper; | ||
using Volumey.Model; | ||
using Xunit; | ||
|
||
namespace Volumey.Tests | ||
{ | ||
public class AudioSessionModelTests | ||
{ | ||
private AudioSessionModel model; | ||
private Mock<IAudioSessionStateNotifications> sessionStateNotif; | ||
|
||
public AudioSessionModelTests() | ||
{ | ||
var sessionVolumeMock = new Mock<IAudioSessionVolume>(); | ||
this.sessionStateNotif = new Mock<IAudioSessionStateNotifications>(); | ||
|
||
this.model = new AudioSessionModel(false, 50, "app", new BitmapImage(), sessionVolumeMock.Object, | ||
sessionStateNotif.Object); | ||
} | ||
|
||
[Fact] | ||
public void VolumeShouldBeChangedToCorrectValue() | ||
{ | ||
var newVolume = this.model.Volume + 1; | ||
|
||
this.sessionStateNotif.Raise(m => m.VolumeChanged += null, | ||
new object[] { new VolumeChangedEventArgs(newVolume, this.model.IsMuted) }); | ||
|
||
Assert.Equal(this.model.Volume, newVolume); | ||
} | ||
|
||
[Fact] | ||
public void MuteStateShouldBeChanged() | ||
{ | ||
var newMuteState = !this.model.IsMuted; | ||
|
||
this.sessionStateNotif.Raise(m => m.VolumeChanged += null, | ||
new object[] { new VolumeChangedEventArgs(this.model.Volume, newMuteState) }); | ||
|
||
Assert.Equal(this.model.IsMuted, newMuteState); | ||
} | ||
|
||
[Fact] | ||
public void IconSourceShouldBeChanged() | ||
{ | ||
var newImageSource = new BitmapImage(); | ||
|
||
this.sessionStateNotif.Raise(m => m.IconPathChanged += null, newImageSource); | ||
|
||
Assert.Equal(this.model.AppIcon, newImageSource); | ||
} | ||
|
||
internal static AudioSessionModel GetSessionMock(string name, int volume, bool muteState) | ||
{ | ||
var sessionVolumeMock = new Mock<IAudioSessionVolume>(); | ||
var sessionStateNotifications = new Mock<IAudioSessionStateNotifications>(); | ||
|
||
return new AudioSessionModel | ||
(muteState, volume, name, null, | ||
sessionVolumeMock.Object, sessionStateNotifications.Object); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Reflection; | ||
using Moq; | ||
using Volumey.CoreAudioWrapper.Wrapper; | ||
using Volumey.DataProvider; | ||
using Volumey.Model; | ||
using Xunit; | ||
|
||
namespace Volumey.Tests | ||
{ | ||
public class DeviceProviderTests | ||
{ | ||
private DeviceProvider model; | ||
private OutputDeviceModel defaultDevice; | ||
|
||
private Mock<IDeviceStateNotificationHandler> deviceStateNotifMock; | ||
|
||
public DeviceProviderTests() | ||
{ | ||
var iDeviceEnumMock = new Mock<IDeviceEnumerator>(); | ||
|
||
deviceStateNotifMock = new Mock<IDeviceStateNotificationHandler>(); | ||
|
||
defaultDevice = OutputDeviceModelTests.GetDeviceMock("111", "speakers", this.deviceStateNotifMock.Object); | ||
var device = OutputDeviceModelTests.GetDeviceMock("123", "device", this.deviceStateNotifMock.Object); | ||
var devices = new List<OutputDeviceModel> {defaultDevice, device}; | ||
iDeviceEnumMock.Setup(m => m.GetCurrentActiveDevices(deviceStateNotifMock.Object)).Returns(devices); | ||
iDeviceEnumMock.Setup(m => m.GetDefaultDeviceId()).Returns(defaultDevice.Id); | ||
|
||
model = GetDeviceProviderMock(iDeviceEnumMock.Object, deviceStateNotifMock.Object); | ||
} | ||
|
||
[Fact] | ||
public void DefaultDeviceShouldReferenceCorrectObject() | ||
{ | ||
Assert.Equal(this.model.DefaultDevice, this.defaultDevice); | ||
} | ||
|
||
[Fact] | ||
public void ActiveDeviceAddedEvent_NewDeviceShouldBeAdded() | ||
{ | ||
var devicesCount = this.model.ActiveDevices.Count; | ||
var newDevice = OutputDeviceModelTests.GetDeviceMock("222", "headphones", this.deviceStateNotifMock.Object); | ||
|
||
this.deviceStateNotifMock.Raise(m => m.ActiveDeviceAdded += null, newDevice); | ||
|
||
Assert.Equal(devicesCount + 1, this.model.ActiveDevices.Count); | ||
Assert.Contains(newDevice, this.model.ActiveDevices); | ||
} | ||
|
||
[Fact] | ||
public void DeviceDisabledEvent_DisabledDeviceShouldBeRemoved() | ||
{ | ||
var deviceCount = model.ActiveDevices.Count; | ||
var disabledDevice = defaultDevice; | ||
|
||
deviceStateNotifMock.Raise(m => m.DeviceDisabled += null, disabledDevice.Id); | ||
|
||
Assert.Equal(deviceCount - 1, model.ActiveDevices.Count); | ||
Assert.DoesNotContain(disabledDevice, this.model.ActiveDevices); | ||
} | ||
|
||
[Fact] | ||
public void FirstDeviceAdded_NoOutputDeviceShouldBeFalse() | ||
{ | ||
//remove all active devices | ||
var activeDevicesCount = this.model.ActiveDevices.Count; | ||
for(int i = activeDevicesCount - 1; i >= 0; i--) | ||
deviceStateNotifMock.Raise(m => m.DeviceDisabled += null, this.model.ActiveDevices[i].Id); | ||
|
||
Assert.True(this.model.NoOutputDevices); | ||
|
||
var newDevice = OutputDeviceModelTests.GetDeviceMock("222", "newDevice", this.deviceStateNotifMock.Object); | ||
deviceStateNotifMock.Raise(m => m.ActiveDeviceAdded += null, newDevice); | ||
|
||
Assert.False(this.model.NoOutputDevices); | ||
Assert.Contains(newDevice, this.model.ActiveDevices); | ||
Assert.Equal(newDevice, this.model.DefaultDevice); | ||
} | ||
|
||
[Fact] | ||
public void DefaultDeviceChangedEvent_DefaultDevicePropertyShouldBeChanged() | ||
{ | ||
var device = OutputDeviceModelTests.GetDeviceMock("222", "headphones", this.deviceStateNotifMock.Object); | ||
deviceStateNotifMock.Raise(m => m.ActiveDeviceAdded += null, device); | ||
|
||
deviceStateNotifMock.Raise(m => m.DefaultDeviceChanged += null, device.Id); | ||
|
||
Assert.Equal(this.model.DefaultDevice, device); | ||
} | ||
|
||
[Fact] | ||
public static void DefaultDeviceShouldNotBeNull_WhenDeviceEnumeratorReturnsInvalidDefaultDeviceId() | ||
{ | ||
var IDeviceEnumMock = new Mock<IDeviceEnumerator>(); | ||
var deviceStateNotificationMock = new Mock<IDeviceStateNotificationHandler>(); | ||
|
||
var device = OutputDeviceModelTests.GetDeviceMock("111", "speakers", deviceStateNotificationMock.Object); | ||
var devices = new List<OutputDeviceModel> {device}; | ||
IDeviceEnumMock.Setup(m => m.GetCurrentActiveDevices(deviceStateNotificationMock.Object)).Returns(devices); | ||
IDeviceEnumMock.Setup(m => m.GetDefaultDeviceId()).Returns(String.Empty); | ||
|
||
var model = (DeviceProvider) Activator.CreateInstance(typeof(DeviceProvider), | ||
BindingFlags.NonPublic | BindingFlags.Instance, null, | ||
new object[] {IDeviceEnumMock.Object, deviceStateNotificationMock.Object}, CultureInfo.InvariantCulture, | ||
null); | ||
|
||
Assert.NotNull(model.DefaultDevice); | ||
} | ||
|
||
public static DeviceProvider GetDeviceProviderMock(IDeviceEnumerator deviceEnum, IDeviceStateNotificationHandler deviceState) | ||
{ | ||
return (DeviceProvider) Activator.CreateInstance(typeof(DeviceProvider), | ||
BindingFlags.NonPublic | BindingFlags.Instance, null, | ||
new object[] {deviceEnum, deviceState}, CultureInfo.InvariantCulture, | ||
null); | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.