Compare commits
18 Commits
b7578de226
...
feature/5-
Author | SHA1 | Date | |
---|---|---|---|
46173f4f99 | |||
4acf091511 | |||
6b14d1264a | |||
bf702e403e | |||
4b22d5d9be | |||
03a091d853 | |||
b2fc0121b0 | |||
589773b29c | |||
9252f96bdb | |||
733649c62b | |||
dd4632cdb6 | |||
9859358d7b | |||
f1a3771912 | |||
4d3413b2a2 | |||
e3eedc5ffa | |||
4ee5656358 | |||
d307a049f1 | |||
36ceb6c61a |
11
.gitea/issue_template.md
Normal file
11
.gitea/issue_template.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
## Story
|
||||||
|
|
||||||
|
**As a**:
|
||||||
|
**I want**:
|
||||||
|
**So that**:
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
## Notes
|
23
README.md
Normal file
23
README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Aurora
|
||||||
|
|
||||||
|
A collaborative media player
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## The Problem Statement
|
||||||
|
|
||||||
|
Music is a medium that should be consumed together. Aurora aims to creat a music listening experience that can be shared with any number of people no matter where the listeners are. With music perfectly in sync between all listeners, remote listening is as easy as loading the app and connecting to your friends.
|
||||||
|
|
||||||
|
## The Tech
|
||||||
|
|
||||||
|
- GTK: Aurora takes advantage of Xamarin and GTK under the hood in order to render a sleek, modern, cross platform desktop application.
|
||||||
|
|
||||||
|
- gRPC: gRPC is a modern open source high performance RPC framework that can run in any environment. This app is inherently a peer to peer application and as such, gRPC is utilized to efficiently and effectively communicate between aurora nodes by implementing simple service definitions.
|
||||||
|
|
||||||
|
## The Future
|
||||||
|
|
||||||
|
We are always looking for ways to improve the exerience of the application.
|
||||||
|
|
||||||
|
- Aurora Turn Server: The next big step for the application is integrating a custom Aurora turn server so that listeners can connect to one another from different networks while maintaining perfectly synchronized output
|
||||||
|
|
||||||
|
- 3rd Party Source Integration: Not everybody has a vast local collection of media that they have been collecting for years. We plan to integrate with 3rd Party music sources such as _Spotify_ and _Apple Music_
|
@ -1,7 +0,0 @@
|
|||||||
namespace Aurora.Services.Signal
|
|
||||||
{
|
|
||||||
public partial class SignalService : Signal.SignalBase
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Protobuf Include="Src\Protos\signal.proto" GrpcServices="Server" />
|
<Protobuf Include="..\..\aurora-proto\Proto\signal.proto" GrpcServices="Server" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,7 +2,7 @@ syntax = "proto3";
|
|||||||
|
|
||||||
package Aurora.Proto.Party;
|
package Aurora.Proto.Party;
|
||||||
|
|
||||||
import "Proto/general.proto";
|
import "general.proto";
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
import "google/protobuf/field_mask.proto";
|
import "google/protobuf/field_mask.proto";
|
||||||
|
|
||||||
@ -105,13 +105,14 @@ message LeavePartyResponse {
|
|||||||
message Member {
|
message Member {
|
||||||
//Resource name of the party member to be returned (Added by server)
|
//Resource name of the party member to be returned (Added by server)
|
||||||
string name = 1;
|
string name = 1;
|
||||||
string userName = 2;
|
string id = 2;
|
||||||
|
string userName = 3;
|
||||||
|
|
||||||
//Added by server
|
//Added by server
|
||||||
string ipAddress = 3;
|
string ipAddress = 4;
|
||||||
|
|
||||||
//Added by server
|
//Added by server
|
||||||
google.protobuf.Timestamp addedOn = 4;
|
google.protobuf.Timestamp addedOn = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListMembersRequest {
|
message ListMembersRequest {
|
351
aurora-shared/.gitignore
vendored
Normal file
351
aurora-shared/.gitignore
vendored
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
start*.sh
|
@ -2,7 +2,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
namespace Aurora.Cursor
|
namespace Aurora.Cursor
|
||||||
{
|
{
|
||||||
public enum SortDirection
|
public enum SortDirection
|
||||||
@ -15,8 +14,8 @@ namespace Aurora.Cursor
|
|||||||
{
|
{
|
||||||
private CursorList<T> _list;
|
private CursorList<T> _list;
|
||||||
|
|
||||||
private string? _previousPageToken;
|
private string _previousPageToken;
|
||||||
private string? _nextPageToken;
|
private string _nextPageToken;
|
||||||
private int _pageSize;
|
private int _pageSize;
|
||||||
private Func<KeyValuePair<string, T>, string> _sortDelgate;
|
private Func<KeyValuePair<string, T>, string> _sortDelgate;
|
||||||
private SortDirection _direction;
|
private SortDirection _direction;
|
@ -4,7 +4,6 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Aurora.Utils;
|
using Aurora.Utils;
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
namespace Aurora.Cursor
|
namespace Aurora.Cursor
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -23,12 +22,8 @@ namespace Aurora.Cursor
|
|||||||
id = HashUtil.GetHash(new string[] { item.GetHashCode().ToString() }).ToString();
|
id = HashUtil.GetHash(new string[] { item.GetHashCode().ToString() }).ToString();
|
||||||
item.Id = id;
|
item.Id = id;
|
||||||
}
|
}
|
||||||
bool res = this.TryAdd(id, item);
|
this.Add(id, item);
|
||||||
|
|
||||||
if (res == false)
|
|
||||||
{
|
|
||||||
throw new System.Exception("Failed to add item to cursor list");
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
8
aurora-shared/aurora-shared.csproj
Normal file
8
aurora-shared/aurora-shared.csproj
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<RootNamespace>aurora_shared</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="..\packages\Xamarin.Forms.4.3.0.991211\build\Xamarin.Forms.props" Condition="Exists('..\packages\Xamarin.Forms.4.3.0.991211\build\Xamarin.Forms.props')" />
|
<Import Project="..\packages\Xamarin.Forms.5.0.0.2012\build\Xamarin.Forms.props" Condition="Exists('..\packages\Xamarin.Forms.5.0.0.2012\build\Xamarin.Forms.props')" />
|
||||||
<Import Project="..\packages\Grpc.Tools.2.25.0\build\Grpc.Tools.props" Condition="Exists('..\packages\Grpc.Tools.2.25.0\build\Grpc.Tools.props')" />
|
<Import Project="..\packages\Grpc.Tools.2.25.0\build\Grpc.Tools.props" Condition="Exists('..\packages\Grpc.Tools.2.25.0\build\Grpc.Tools.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@ -28,42 +28,24 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="gtk-sharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="gdk-sharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="glib-sharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="glade-sharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="pango-sharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="atk-sharp, Version=2.4.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
|
|
||||||
<SpecificVersion>False</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Mono.Posix" />
|
<Reference Include="Mono.Posix" />
|
||||||
<Reference Include="Xamarin.Forms.Core">
|
<Reference Include="Xamarin.Forms.Core">
|
||||||
<HintPath>..\packages\Xamarin.Forms.4.3.0.991211\lib\netstandard2.0\Xamarin.Forms.Core.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Forms.5.0.0.2012\lib\netstandard2.0\Xamarin.Forms.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Forms.Platform">
|
<Reference Include="Xamarin.Forms.Platform">
|
||||||
<HintPath>..\packages\Xamarin.Forms.4.3.0.991211\lib\netstandard2.0\Xamarin.Forms.Platform.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Forms.5.0.0.2012\lib\netstandard2.0\Xamarin.Forms.Platform.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Forms.Xaml">
|
<Reference Include="Xamarin.Forms.Xaml">
|
||||||
<HintPath>..\packages\Xamarin.Forms.4.3.0.991211\lib\netstandard2.0\Xamarin.Forms.Xaml.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Forms.5.0.0.2012\lib\netstandard2.0\Xamarin.Forms.Xaml.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="OpenTK">
|
<Reference Include="OpenTK">
|
||||||
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
|
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="webkit-sharp">
|
<Reference Include="webkit-sharp">
|
||||||
<HintPath>..\packages\Xamarin.Forms.Platform.GTK.4.3.0.991211\lib\net45\webkit-sharp.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Forms.Platform.GTK.5.0.0.2012\lib\net45\webkit-sharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Forms.Platform.GTK">
|
<Reference Include="Xamarin.Forms.Platform.GTK">
|
||||||
<HintPath>..\packages\Xamarin.Forms.Platform.GTK.4.3.0.991211\lib\net45\Xamarin.Forms.Platform.GTK.dll</HintPath>
|
<HintPath>..\packages\Xamarin.Forms.Platform.GTK.5.0.0.2012\lib\net45\Xamarin.Forms.Platform.GTK.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Reflection">
|
<Reference Include="System.Reflection">
|
||||||
<HintPath>..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
|
<HintPath>..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
|
||||||
@ -168,6 +150,15 @@
|
|||||||
<HintPath>..\packages\Autofac.5.0.0\lib\net461\Autofac.dll</HintPath>
|
<HintPath>..\packages\Autofac.5.0.0\lib\net461\Autofac.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.ComponentModel.Composition" />
|
<Reference Include="System.ComponentModel.Composition" />
|
||||||
|
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
<Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
<Reference Include="Xamarin.Forms.DataGrid">
|
||||||
|
<HintPath>..\packages\Xamarin.Forms.DataGrid.4.8.0\lib\netstandard2.0\Xamarin.Forms.DataGrid.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="gtk-gui\gui.stetic">
|
<EmbeddedResource Include="gtk-gui\gui.stetic">
|
||||||
@ -514,6 +505,7 @@
|
|||||||
<Project>{17F51282-39BE-4FE3-8EC7-6D108F5DD0FD}</Project>
|
<Project>{17F51282-39BE-4FE3-8EC7-6D108F5DD0FD}</Project>
|
||||||
<Name>Aurora</Name>
|
<Name>Aurora</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\aurora-shared\aurora-shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Resources\play.png">
|
<Content Include="Resources\play.png">
|
||||||
@ -545,5 +537,5 @@
|
|||||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
|
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
|
||||||
<Import Project="..\packages\Grpc.Core.2.25.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.2.25.0\build\net45\Grpc.Core.targets')" />
|
<Import Project="..\packages\Grpc.Core.2.25.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.2.25.0\build\net45\Grpc.Core.targets')" />
|
||||||
<Import Project="..\packages\VideoLAN.LibVLC.Mac.3.1.3.1\build\VideoLAN.LibVLC.Mac.targets" Condition="Exists('..\packages\VideoLAN.LibVLC.Mac.3.1.3.1\build\VideoLAN.LibVLC.Mac.targets')" />
|
<Import Project="..\packages\VideoLAN.LibVLC.Mac.3.1.3.1\build\VideoLAN.LibVLC.Mac.targets" Condition="Exists('..\packages\VideoLAN.LibVLC.Mac.3.1.3.1\build\VideoLAN.LibVLC.Mac.targets')" />
|
||||||
<Import Project="..\packages\Xamarin.Forms.4.3.0.991211\build\Xamarin.Forms.targets" Condition="Exists('..\packages\Xamarin.Forms.4.3.0.991211\build\Xamarin.Forms.targets')" />
|
<Import Project="..\packages\Xamarin.Forms.5.0.0.2012\build\Xamarin.Forms.targets" Condition="Exists('..\packages\Xamarin.Forms.5.0.0.2012\build\Xamarin.Forms.targets')" />
|
||||||
</Project>
|
</Project>
|
@ -2,6 +2,7 @@
|
|||||||
<stetic-interface>
|
<stetic-interface>
|
||||||
<configuration>
|
<configuration>
|
||||||
<images-root-path>..</images-root-path>
|
<images-root-path>..</images-root-path>
|
||||||
|
<target-gtk-version>2.12</target-gtk-version>
|
||||||
</configuration>
|
</configuration>
|
||||||
<import>
|
<import>
|
||||||
<widget-library name="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
<widget-library name="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<package id="Grpc.Core" version="2.25.0" targetFramework="net47" />
|
<package id="Grpc.Core" version="2.25.0" targetFramework="net47" />
|
||||||
<package id="Grpc.Core.Api" version="2.25.0" targetFramework="net47" />
|
<package id="Grpc.Core.Api" version="2.25.0" targetFramework="net47" />
|
||||||
<package id="Grpc.Tools" version="2.25.0" targetFramework="net47" developmentDependency="true" />
|
<package id="Grpc.Tools" version="2.25.0" targetFramework="net47" developmentDependency="true" />
|
||||||
<package id="LibVLCSharp" version="3.3.1" targetFramework="net47" />
|
<package id="LibVLCSharp" version="3.3.1" targetFramework="net47" requireReinstallation="true" />
|
||||||
<package id="LibVLCSharp.Forms" version="3.3.1" targetFramework="net47" />
|
<package id="LibVLCSharp.Forms" version="3.3.1" targetFramework="net47" />
|
||||||
<package id="LibVLCSharp.Forms.GTK" version="3.3.1" targetFramework="net47" />
|
<package id="LibVLCSharp.Forms.GTK" version="3.3.1" targetFramework="net47" />
|
||||||
<package id="LibVLCSharp.GTK" version="3.3.1" targetFramework="net47" />
|
<package id="LibVLCSharp.GTK" version="3.3.1" targetFramework="net47" />
|
||||||
@ -25,7 +25,7 @@
|
|||||||
<package id="System.Memory" version="4.5.3" targetFramework="net47" />
|
<package id="System.Memory" version="4.5.3" targetFramework="net47" />
|
||||||
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net47" />
|
<package id="System.Numerics.Vectors" version="4.4.0" targetFramework="net47" />
|
||||||
<package id="System.Reflection" version="4.3.0" targetFramework="net47" />
|
<package id="System.Reflection" version="4.3.0" targetFramework="net47" />
|
||||||
<package id="System.Reflection.TypeExtensions" version="4.6.0" targetFramework="net47" />
|
<package id="System.Reflection.TypeExtensions" version="4.6.0" targetFramework="net47" requireReinstallation="true" />
|
||||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net47" />
|
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net47" />
|
||||||
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net47" />
|
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net47" />
|
||||||
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="net47" />
|
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="net47" />
|
||||||
@ -34,6 +34,7 @@
|
|||||||
<package id="taglib-sharp-netstandard2.0" version="2.1.0" targetFramework="net47" />
|
<package id="taglib-sharp-netstandard2.0" version="2.1.0" targetFramework="net47" />
|
||||||
<package id="VideoLAN.LibVLC.Mac" version="3.1.3.1" targetFramework="net47" />
|
<package id="VideoLAN.LibVLC.Mac" version="3.1.3.1" targetFramework="net47" />
|
||||||
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="net47" />
|
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="net47" />
|
||||||
<package id="Xamarin.Forms" version="4.3.0.991211" targetFramework="net47" />
|
<package id="Xamarin.Forms" version="5.0.0.2012" targetFramework="net47" />
|
||||||
<package id="Xamarin.Forms.Platform.GTK" version="4.3.0.991211" targetFramework="net47" />
|
<package id="Xamarin.Forms.DataGrid" version="4.8.0" targetFramework="net47" />
|
||||||
|
<package id="Xamarin.Forms.Platform.GTK" version="5.0.0.2012" targetFramework="net47" />
|
||||||
</packages>
|
</packages>
|
@ -5,8 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aurora", "Aurora\Aurora.csp
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aurora.gtk", "Aurora.gtk\Aurora.gtk.csproj", "{E8C8C24A-5C51-47CB-B241-F5A9F0E808B1}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aurora.gtk", "Aurora.gtk\Aurora.gtk.csproj", "{E8C8C24A-5C51-47CB-B241-F5A9F0E808B1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aurora.test", "Aurora.test\Aurora.test.csproj", "{45680D8A-1AF1-4D93-AAC0-59CDB01CED5D}"
|
#Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aurora.test", "Aurora.test\Aurora.test.csproj", "{45680D8A-1AF1-4D93-AAC0-59CDB01CED5D}"
|
||||||
EndProject
|
#EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -21,11 +21,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Aurora\Aurora.csproj" />
|
<ProjectReference Include="..\Aurora\Aurora.csproj" />
|
||||||
|
<ProjectReference Include="..\..\aurora-shared\aurora-shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Resources\Jidenna\The Chief\01 A Bull%27s Tale.mp3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Jidenna\The Chief\04 Bambi.mp3">
|
<None Update="Resources\Jidenna\The Chief\04 Bambi.mp3">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
@ -56,62 +54,11 @@
|
|||||||
<None Update="Resources\Jidenna\The Chief\06 Long Live The Chief.mp3">
|
<None Update="Resources\Jidenna\The Chief\06 Long Live The Chief.mp3">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="Resources\Jidenna\The Chief\02 Chief Don%27t Run.mp3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Jidenna\The Chief\11 Little Bit More.mp3">
|
<None Update="Resources\Jidenna\The Chief\11 Little Bit More.mp3">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="Resources\Jidenna\The Chief\13 White Niggas.mp3">
|
<None Update="Resources\Jidenna\The Chief\13 White Niggas.mp3">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\16 BDE Bonus %28Prod. By_ ID Labs%29.mp3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\11 Play Ya Cards %28Prod By_ Chuck Inglish%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\08 All Around The World %28Prod. By_ Just Blaze%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\10 In The Air %28Prod By_ Ritz Reynolds%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\05 I%27ll Be There %28feat. Phonte%29 %28Prod. By_ Beanz %27n%27 Kornbread%29.mp3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\03 Donald Trump %28Prod. By_ Sap%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\13 Life Ain%27t Easy %28Prod. By_ ID Labs%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\09 Down The Rabbit Hole %28Prod. By_ Blue of The Sore Losers%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\07 Wake Up %28Prod By_ Sap & ID Labs%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\04 Oy Vey %28Prod By_ ID Labs%29.mp3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\01 Best Day Ever %28Prod. By_ ID Labs%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\02 Get Up %28Prod. By_ Teddy Roxpin%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\14 Snooze %28Prod By_ ID Labs%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\12 She Said %28Prod By_ Khrysis%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\15 Keep Floatin%27 %28feat. Wiz Khalifa%29 %28Prod. By_ ID Labs%29.mp3">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Resources\Mac Miller\Best Day Ever\06 Wear My Hat %28Prod. By_ Chuck Inglish%29.m4a">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -7,8 +7,7 @@ using Aurora.Design.Views.Profile;
|
|||||||
using Aurora.Design.Views.Songs;
|
using Aurora.Design.Views.Songs;
|
||||||
using Aurora.Design.Views.Stations;
|
using Aurora.Design.Views.Stations;
|
||||||
using Aurora.Services.EventManager;
|
using Aurora.Services.EventManager;
|
||||||
using Aurora.Services.Server;
|
using Aurora.Services;
|
||||||
using Aurora.Services.Client;
|
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using LibVLCSharp.Shared;
|
using LibVLCSharp.Shared;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@ -28,19 +27,19 @@ namespace Aurora
|
|||||||
|
|
||||||
//Register DI
|
//Register DI
|
||||||
ContainerBuilder _builder = new ContainerBuilder();
|
ContainerBuilder _builder = new ContainerBuilder();
|
||||||
// _builder.RegisterInstance<IPlayer>(new PlayerService()).SingleInstance();
|
_builder.RegisterInstance<IPlayer>(new PlayerService()).SingleInstance();
|
||||||
|
_builder.RegisterType<Global>().As<Global>().SingleInstance();
|
||||||
_builder.RegisterType<PlayerService>().As<IPlayer>().SingleInstance();
|
_builder.RegisterType<PlayerService>().As<IPlayer>().SingleInstance();
|
||||||
_builder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
|
_builder.RegisterType<SettingsService>().As<ISettingsService>().SingleInstance();
|
||||||
_builder.RegisterType<LibraryService>().As<ILibraryService>().SingleInstance();
|
_builder.RegisterType<LibraryService>().As<ILibraryService>().SingleInstance();
|
||||||
_builder.RegisterType<EventManager>().As<IEventManager>().SingleInstance();
|
_builder.RegisterType<EventManager>().As<IEventManager>().SingleInstance();
|
||||||
_builder.RegisterType<ServerService>().As<IServerService>().SingleInstance();
|
|
||||||
_builder.RegisterType<ClientService>().As<IClientService>().SingleInstance();
|
|
||||||
_builder.RegisterType<MainView>().SingleInstance();
|
_builder.RegisterType<MainView>().SingleInstance();
|
||||||
_builder.RegisterType<AlbumsViewModel>();
|
_builder.RegisterType<AlbumsViewModel>();
|
||||||
_builder.RegisterType<ArtistsViewModel>();
|
_builder.RegisterType<ArtistsViewModel>();
|
||||||
_builder.RegisterType<PartyViewModel>();
|
_builder.RegisterType<PartyViewModel>();
|
||||||
_builder.RegisterType<ProfileViewModel>();
|
_builder.RegisterType<ProfileViewModel>();
|
||||||
_builder.RegisterType<SongsViewModel>();
|
_builder.RegisterType<SongsViewModel>();
|
||||||
|
_builder.RegisterType<HostPartyViewModel>();
|
||||||
_builder.RegisterType<StationsViewModel>();
|
_builder.RegisterType<StationsViewModel>();
|
||||||
|
|
||||||
// _builder.RegisterInstance<ISettingsService>(new SettingsService()).SingleInstance();
|
// _builder.RegisterInstance<ISettingsService>(new SettingsService()).SingleInstance();
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<OutputPath></OutputPath>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Xamarin.Forms" Version="4.3.0.991211" />
|
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2012" />
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
|
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
||||||
<PackageReference Include="taglib-sharp-netstandard2.0" Version="2.1.0" />
|
<PackageReference Include="taglib-sharp-netstandard2.0" Version="2.1.0" />
|
||||||
<PackageReference Include="LibVLCSharp.Forms" Version="3.3.1" />
|
<PackageReference Include="LibVLCSharp.Forms" Version="3.3.1" />
|
||||||
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
|
<PackageReference Include="VideoLAN.LibVLC.Mac" Version="3.1.3.1" />
|
||||||
@ -24,6 +25,7 @@
|
|||||||
<PackageReference Include="DLToolkit.Forms.Controls.FlowListView" Version="2.0.11" />
|
<PackageReference Include="DLToolkit.Forms.Controls.FlowListView" Version="2.0.11" />
|
||||||
<PackageReference Include="CarouselView.FormsPlugin" Version="5.2.0" />
|
<PackageReference Include="CarouselView.FormsPlugin" Version="5.2.0" />
|
||||||
<PackageReference Include="Autofac" Version="5.0.0" />
|
<PackageReference Include="Autofac" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Xamarin.Forms.DataGrid" Version="4.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Design\" />
|
<Folder Include="Design\" />
|
||||||
@ -43,7 +45,6 @@
|
|||||||
<Folder Include="Design\Components\MemberList\" />
|
<Folder Include="Design\Components\MemberList\" />
|
||||||
<Folder Include="Design\Components\Library\" />
|
<Folder Include="Design\Components\Library\" />
|
||||||
<Folder Include="Design\Views\Profile\" />
|
<Folder Include="Design\Views\Profile\" />
|
||||||
<Folder Include="Design\Components\DataGrid\" />
|
|
||||||
<Folder Include="Resources\" />
|
<Folder Include="Resources\" />
|
||||||
<Folder Include="Design\Extensions\" />
|
<Folder Include="Design\Extensions\" />
|
||||||
<Folder Include="Design\Components\ImageButton\" />
|
<Folder Include="Design\Components\ImageButton\" />
|
||||||
@ -60,8 +61,8 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Protobuf Include="Proto\general.proto" />
|
<Protobuf Include="..\..\aurora-proto\Proto\general.proto" />
|
||||||
<Protobuf Include="Proto\party.proto" />
|
<Protobuf Include="..\..\aurora-proto\Proto\party.proto" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Resources\backward.png" />
|
<EmbeddedResource Include="Resources\backward.png" />
|
||||||
@ -82,4 +83,7 @@
|
|||||||
<None Remove="Resources\like.png" />
|
<None Remove="Resources\like.png" />
|
||||||
<None Remove="Resources\play.png" />
|
<None Remove="Resources\play.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\aurora-shared\aurora-shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,8 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public sealed class ColumnCollection : List<DataGridColumn>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Grid
|
|
||||||
x:Name="self"
|
|
||||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
|
||||||
x:Class="Aurora.Design.Components.DataGrid.DataGrid"
|
|
||||||
Padding="0"
|
|
||||||
RowSpacing="0">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition
|
|
||||||
Height="Auto"/>
|
|
||||||
<RowDefinition
|
|
||||||
Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid
|
|
||||||
x:Name="_headerView"
|
|
||||||
RowSpacing="0">
|
|
||||||
<Grid.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<!--Default Header Style-->
|
|
||||||
<Style
|
|
||||||
x:Key="HeaderDefaultStyle"
|
|
||||||
TargetType="Label">
|
|
||||||
<Setter
|
|
||||||
Property="FontSize"
|
|
||||||
Value="{Binding HeaderFontSize, Source={x:Reference self}}"/>
|
|
||||||
<Setter
|
|
||||||
Property="FontAttributes"
|
|
||||||
Value="Bold"/>
|
|
||||||
<Setter
|
|
||||||
Property="HorizontalOptions"
|
|
||||||
Value="Center"/>
|
|
||||||
<Setter
|
|
||||||
Property="VerticalOptions"
|
|
||||||
Value="Center"/>
|
|
||||||
<Setter
|
|
||||||
Property="TextColor"
|
|
||||||
Value="{Binding HeaderTextColor,Source={x:Reference self}}"/>
|
|
||||||
<Setter
|
|
||||||
Property="LineBreakMode"
|
|
||||||
Value="WordWrap"/>
|
|
||||||
</Style>
|
|
||||||
<Style
|
|
||||||
TargetType="Grid">
|
|
||||||
<Setter
|
|
||||||
Property="BackgroundColor"
|
|
||||||
Value="{Binding HeaderBackground,Source={x:Reference self}}"/>
|
|
||||||
</Style>
|
|
||||||
<Style
|
|
||||||
x:Key="ImageStyleBase"
|
|
||||||
TargetType="Image">
|
|
||||||
<Setter
|
|
||||||
Property="Aspect"
|
|
||||||
Value="AspectFill"/>
|
|
||||||
<Setter
|
|
||||||
Property="VerticalOptions"
|
|
||||||
Value="Center"/>
|
|
||||||
<Setter
|
|
||||||
Property="HorizontalOptions"
|
|
||||||
Value="Center"/>
|
|
||||||
<Setter
|
|
||||||
Property="HeightRequest"
|
|
||||||
Value="5"/>
|
|
||||||
<Setter
|
|
||||||
Property="WidthRequest"
|
|
||||||
Value="9"/>
|
|
||||||
<Setter
|
|
||||||
Property="Margin"
|
|
||||||
Value="0,0,4,0"/>
|
|
||||||
</Style>
|
|
||||||
<Style
|
|
||||||
x:Key="AscendingIconStyle"
|
|
||||||
TargetType="Image"
|
|
||||||
BasedOn="{StaticResource ImageStyleBase}">
|
|
||||||
<Setter
|
|
||||||
Property="Source"
|
|
||||||
Value="{Binding AscendingIcon, Source={x:Reference self}}"/>
|
|
||||||
</Style>
|
|
||||||
<Style
|
|
||||||
x:Key="DescendingIconStyle"
|
|
||||||
TargetType="Image"
|
|
||||||
BasedOn="{StaticResource ImageStyleBase}">
|
|
||||||
<Setter
|
|
||||||
Property="Source"
|
|
||||||
Value="{Binding DescendingIcon, Source={x:Reference self}}"/>
|
|
||||||
</Style>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</Grid.Resources>
|
|
||||||
</Grid>
|
|
||||||
<ListView x:Name="DataList" Grid.Row="1" BackgroundColor="#222222" />
|
|
||||||
<ContentView
|
|
||||||
x:Name="_noDataView"
|
|
||||||
Grid.RowSpan="2"
|
|
||||||
IsVisible="False"/>
|
|
||||||
</Grid>
|
|
@ -1,756 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
using Aurora.Utils;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public partial class DataGrid : Grid
|
|
||||||
{
|
|
||||||
#region Private Fields
|
|
||||||
private ObservableCollection<object> _internalItems;
|
|
||||||
|
|
||||||
private Dictionary<int, SortingOrder> _sortingOrders;
|
|
||||||
|
|
||||||
#endregion Fields
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public DataGrid() : this(ListViewCachingStrategy.RetainElement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataGrid(ListViewCachingStrategy cachingStrategy)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
BackgroundColor = Color.Transparent;
|
|
||||||
|
|
||||||
_sortingOrders = new Dictionary<int, SortingOrder>();
|
|
||||||
|
|
||||||
DataList.ItemTemplate = new DataGridRowTemplateSelector();
|
|
||||||
|
|
||||||
DataList.ItemSelected += (s, e) =>
|
|
||||||
{
|
|
||||||
if (SelectionEnabled)
|
|
||||||
{
|
|
||||||
SelectedItem = DataList.SelectedItem;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DataList.SelectedItem = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemSelected?.Invoke(this, e);
|
|
||||||
};
|
|
||||||
|
|
||||||
DataList.Refreshing += (s, e) =>
|
|
||||||
{
|
|
||||||
Refreshing?.Invoke(this, e);
|
|
||||||
};
|
|
||||||
|
|
||||||
DataList.SetBinding(ListView.RowHeightProperty, new Binding("RowHeight", source: this));
|
|
||||||
}
|
|
||||||
#endregion Constructor
|
|
||||||
|
|
||||||
#region Public Fields
|
|
||||||
public event EventHandler Refreshing;
|
|
||||||
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
|
|
||||||
|
|
||||||
#endregion Public Fields
|
|
||||||
|
|
||||||
#region Bindable properties
|
|
||||||
public static readonly BindableProperty ActiveRowColorProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(ActiveRowColor),
|
|
||||||
typeof(Color),
|
|
||||||
typeof(DataGrid),
|
|
||||||
Color.FromRgb(128, 144, 160),
|
|
||||||
coerceValue: (bindable, value) =>
|
|
||||||
{
|
|
||||||
if (!(bindable as DataGrid).SelectionEnabled)
|
|
||||||
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set ActiveRowColor");
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderBackgroundProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(HeaderBackground),
|
|
||||||
typeof(Color),
|
|
||||||
typeof(DataGrid),
|
|
||||||
Color.White,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (self._headerView != null && !self.HeaderBordersVisible)
|
|
||||||
self._headerView.BackgroundColor = (Color)newValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty BorderColorProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(BorderColor),
|
|
||||||
typeof(Color),
|
|
||||||
typeof(DataGrid),
|
|
||||||
Color.Black,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (self.HeaderBordersVisible)
|
|
||||||
self._headerView.BackgroundColor = (Color)newValue;
|
|
||||||
|
|
||||||
if (self.Columns != null && self.ItemsSource != null)
|
|
||||||
self.Reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty RowsBackgroundColorPaletteProperty =
|
|
||||||
BindableProperty.Create(nameof(RowsBackgroundColorPalette),
|
|
||||||
typeof(IColorProvider),
|
|
||||||
typeof(DataGrid),
|
|
||||||
new PaletteCollection { default(Color) },
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (self.Columns != null && self.ItemsSource != null)
|
|
||||||
self.Reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty RowsTextColorPaletteProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(RowsTextColorPalette),
|
|
||||||
typeof(IColorProvider),
|
|
||||||
typeof(DataGrid),
|
|
||||||
new PaletteCollection { Color.Black },
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (self.Columns != null && self.ItemsSource != null)
|
|
||||||
self.Reload();
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty ColumnsProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(Columns),
|
|
||||||
typeof(ColumnCollection),
|
|
||||||
typeof(DataGrid),
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
(bindable as DataGrid).InitHeaderView();
|
|
||||||
},
|
|
||||||
defaultValueCreator: bindable => { return new ColumnCollection(); }
|
|
||||||
);
|
|
||||||
|
|
||||||
public static BindableProperty ItemsSourceProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
propertyName: nameof(ItemsSource),
|
|
||||||
returnType: typeof(IEnumerable),
|
|
||||||
declaringType: typeof(DataGrid),
|
|
||||||
defaultBindingMode: BindingMode.TwoWay,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
DataGrid self = bindable as DataGrid;
|
|
||||||
//ObservableCollection Tracking
|
|
||||||
if (oldValue != null && oldValue is INotifyCollectionChanged)
|
|
||||||
{
|
|
||||||
(oldValue as INotifyCollectionChanged).CollectionChanged -= self.HandleItemsSourceCollectionChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newValue != null && newValue is INotifyCollectionChanged)
|
|
||||||
{
|
|
||||||
(newValue as INotifyCollectionChanged).CollectionChanged += self.HandleItemsSourceCollectionChanged;
|
|
||||||
|
|
||||||
self.InternalItems = new ObservableCollection<object>(((IEnumerable<object>)newValue));
|
|
||||||
//Assign listview item source
|
|
||||||
self.DataList.ItemsSource = self.InternalItems;
|
|
||||||
self.DataList.SetBinding(ListView.ItemsSourceProperty, new Binding("ItemsSource", source: self));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.SelectedItem != null && !self.InternalItems.Contains(self.SelectedItem))
|
|
||||||
{
|
|
||||||
self.SelectedItem = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.NoDataView != null)
|
|
||||||
{
|
|
||||||
if (self.ItemsSource == null || self.InternalItems.Count() == 0)
|
|
||||||
{
|
|
||||||
self._noDataView.IsVisible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (self._noDataView.IsVisible)
|
|
||||||
{
|
|
||||||
self._noDataView.IsVisible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
private void HandleItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (e.NewItems != null)
|
|
||||||
{
|
|
||||||
foreach (object item in e.NewItems)
|
|
||||||
{
|
|
||||||
InternalItems.Add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.OldItems != null)
|
|
||||||
{
|
|
||||||
foreach (object item in e.OldItems)
|
|
||||||
{
|
|
||||||
InternalItems.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (SelectedItem != null && !InternalItems.Contains(SelectedItem))
|
|
||||||
{
|
|
||||||
SelectedItem = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly BindableProperty RowHeightProperty =
|
|
||||||
BindableProperty.Create(nameof(RowHeight), typeof(int), typeof(DataGrid), 40,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
self.DataList.RowHeight = (int)newValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderHeightProperty =
|
|
||||||
BindableProperty.Create(nameof(HeaderHeight), typeof(int), typeof(DataGrid), 40,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
self._headerView.HeightRequest = (int)newValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty IsSortableProperty =
|
|
||||||
BindableProperty.Create(nameof(IsSortable), typeof(bool), typeof(DataGrid), true);
|
|
||||||
|
|
||||||
public static readonly BindableProperty FontSizeProperty =
|
|
||||||
BindableProperty.Create(nameof(FontSize), typeof(double), typeof(DataGrid), 13.0);
|
|
||||||
|
|
||||||
public static readonly BindableProperty FontFamilyProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(FontFamily),
|
|
||||||
typeof(string),
|
|
||||||
typeof(DataGrid),
|
|
||||||
Font.Default.FontFamily);
|
|
||||||
|
|
||||||
public static readonly BindableProperty SelectedItemProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(SelectedItem),
|
|
||||||
typeof(object),
|
|
||||||
typeof(DataGrid),
|
|
||||||
null,
|
|
||||||
BindingMode.TwoWay,
|
|
||||||
coerceValue: (bindable, value) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (!self.SelectionEnabled && value != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Datagrid must be SelectionEnabled=true to set SelectedItem");
|
|
||||||
}
|
|
||||||
if (self.InternalItems != null && self.InternalItems.Contains(value))
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (self.DataList.SelectedItem != newValue)
|
|
||||||
{
|
|
||||||
self.DataList.SelectedItem = newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
public static readonly BindableProperty SelectionEnabledProperty =
|
|
||||||
BindableProperty.Create(nameof(SelectionEnabled), typeof(bool), typeof(DataGrid), true,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (!self.SelectionEnabled && self.SelectedItem != null)
|
|
||||||
{
|
|
||||||
self.SelectedItem = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty PullToRefreshCommandProperty =
|
|
||||||
BindableProperty.Create(nameof(PullToRefreshCommand), typeof(ICommand), typeof(DataGrid), null,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (newValue == null)
|
|
||||||
{
|
|
||||||
self.DataList.IsPullToRefreshEnabled = false;
|
|
||||||
self.DataList.RefreshCommand = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.DataList.IsPullToRefreshEnabled = true;
|
|
||||||
self.DataList.RefreshCommand = newValue as ICommand;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty IsRefreshingProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(IsRefreshing),
|
|
||||||
typeof(bool),
|
|
||||||
typeof(DataGrid),
|
|
||||||
false,
|
|
||||||
BindingMode.TwoWay,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
(bindable as DataGrid).DataList.IsRefreshing = (bool)newValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty BorderThicknessProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(BorderThickness),
|
|
||||||
typeof(Thickness),
|
|
||||||
typeof(DataGrid),
|
|
||||||
new Thickness(1),
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
(bindable as DataGrid)._headerView.ColumnSpacing = ((Thickness)newValue).HorizontalThickness / 2;
|
|
||||||
(bindable as DataGrid)._headerView.Padding = ((Thickness)newValue).HorizontalThickness / 2;
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderBordersVisibleProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(HeaderBordersVisible),
|
|
||||||
typeof(bool),
|
|
||||||
typeof(DataGrid),
|
|
||||||
true,
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) => (bindable as DataGrid)._headerView.BackgroundColor = (bool)newValue ? (bindable as DataGrid).BorderColor : (bindable as DataGrid).HeaderBackground);
|
|
||||||
|
|
||||||
public static readonly BindableProperty SortedColumnIndexProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(SortedColumnIndex),
|
|
||||||
typeof(SortData),
|
|
||||||
typeof(DataGrid),
|
|
||||||
null,
|
|
||||||
BindingMode.TwoWay,
|
|
||||||
validateValue: (bindable, v) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
var sData = (SortData)v;
|
|
||||||
|
|
||||||
return
|
|
||||||
sData == null || //setted to null
|
|
||||||
self.Columns == null || // Columns binded but not setted
|
|
||||||
self.Columns.Count == 0 || //columns not setted yet
|
|
||||||
(sData.Index < self.Columns.Count && self.Columns.ElementAt(sData.Index).SortingEnabled);
|
|
||||||
},
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if (oldValue != newValue)
|
|
||||||
self.SortItems((SortData)newValue);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderLabelStyleProperty =
|
|
||||||
BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGrid));
|
|
||||||
|
|
||||||
public static readonly BindableProperty AscendingIconProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(AscendingIcon),
|
|
||||||
typeof(ImageSource),
|
|
||||||
typeof(DataGrid),
|
|
||||||
ImageSource.FromResource("Xamarin.Forms.DataGrid.up.png",
|
|
||||||
typeof(DataGrid).GetTypeInfo().Assembly));
|
|
||||||
|
|
||||||
public static readonly BindableProperty DescendingIconProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(DescendingIcon),
|
|
||||||
typeof(ImageSource),
|
|
||||||
typeof(DataGrid),
|
|
||||||
ImageSource.FromResource("Xamarin.Forms.DataGrid.down.png",
|
|
||||||
typeof(DataGrid).GetTypeInfo().Assembly));
|
|
||||||
|
|
||||||
public static readonly BindableProperty DescendingIconStyleProperty =
|
|
||||||
BindableProperty.Create(nameof(DescendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
|
||||||
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
var style = (newValue as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
|
||||||
if (style != null)
|
|
||||||
{
|
|
||||||
if (style.Value is string vs)
|
|
||||||
self.DescendingIcon = ImageSource.FromFile(vs);
|
|
||||||
else
|
|
||||||
self.DescendingIcon = (ImageSource)style.Value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty AscendingIconStyleProperty =
|
|
||||||
BindableProperty.Create(nameof(AscendingIconStyle), typeof(Style), typeof(DataGrid), null,
|
|
||||||
coerceValue: (bindable, v) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
},
|
|
||||||
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
var self = bindable as DataGrid;
|
|
||||||
if ((newValue as Style).Setters.Any(x => x.Property == Image.SourceProperty))
|
|
||||||
{
|
|
||||||
var style = (newValue as Style).Setters.FirstOrDefault(x => x.Property == Image.SourceProperty);
|
|
||||||
if (style != null)
|
|
||||||
{
|
|
||||||
if (style.Value is string vs)
|
|
||||||
self.AscendingIcon = ImageSource.FromFile(vs);
|
|
||||||
else
|
|
||||||
self.AscendingIcon = (ImageSource)style.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty NoDataViewProperty =
|
|
||||||
BindableProperty.Create(nameof(NoDataView), typeof(View), typeof(DataGrid),
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
if (oldValue != newValue)
|
|
||||||
(bindable as DataGrid)._noDataView.Content = newValue as View;
|
|
||||||
});
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public Color ActiveRowColor
|
|
||||||
{
|
|
||||||
get { return (Color)GetValue(ActiveRowColorProperty); }
|
|
||||||
set { SetValue(ActiveRowColorProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color HeaderBackground
|
|
||||||
{
|
|
||||||
get { return (Color)GetValue(HeaderBackgroundProperty); }
|
|
||||||
set { SetValue(HeaderBackgroundProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Please use HeaderLabelStyle", true)]
|
|
||||||
public Color HeaderTextColor
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color BorderColor
|
|
||||||
{
|
|
||||||
get { return (Color)GetValue(BorderColorProperty); }
|
|
||||||
set { SetValue(BorderColorProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IColorProvider RowsBackgroundColorPalette
|
|
||||||
{
|
|
||||||
get { return (IColorProvider)GetValue(RowsBackgroundColorPaletteProperty); }
|
|
||||||
set { SetValue(RowsBackgroundColorPaletteProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IColorProvider RowsTextColorPalette
|
|
||||||
{
|
|
||||||
get { return (IColorProvider)GetValue(RowsTextColorPaletteProperty); }
|
|
||||||
set { SetValue(RowsTextColorPaletteProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable ItemsSource
|
|
||||||
{
|
|
||||||
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
|
|
||||||
set { SetValue(ItemsSourceProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ObservableCollection<object> InternalItems
|
|
||||||
{
|
|
||||||
get { return _internalItems; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != _internalItems)
|
|
||||||
{
|
|
||||||
_internalItems = value;
|
|
||||||
if (IsSortable && SortedColumnIndex != null)
|
|
||||||
{
|
|
||||||
SortItems(SortedColumnIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataList.ItemsSource = _internalItems;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ColumnCollection Columns
|
|
||||||
{
|
|
||||||
get { return (ColumnCollection)GetValue(ColumnsProperty); }
|
|
||||||
set { SetValue(ColumnsProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public double FontSize
|
|
||||||
{
|
|
||||||
get { return (double)GetValue(FontSizeProperty); }
|
|
||||||
set { SetValue(FontSizeProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Please use HeaderLabelStyle", true)]
|
|
||||||
public double HeaderFontSize
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FontFamily
|
|
||||||
{
|
|
||||||
get { return (string)GetValue(FontFamilyProperty); }
|
|
||||||
set { SetValue(FontFamilyProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RowHeight
|
|
||||||
{
|
|
||||||
get { return (int)GetValue(RowHeightProperty); }
|
|
||||||
set { SetValue(RowHeightProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int HeaderHeight
|
|
||||||
{
|
|
||||||
get { return (int)GetValue(HeaderHeightProperty); }
|
|
||||||
set { SetValue(HeaderHeightProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSortable
|
|
||||||
{
|
|
||||||
get { return (bool)GetValue(IsSortableProperty); }
|
|
||||||
set { SetValue(IsSortableProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SelectionEnabled
|
|
||||||
{
|
|
||||||
get { return (bool)GetValue(SelectionEnabledProperty); }
|
|
||||||
set { SetValue(SelectionEnabledProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public object SelectedItem
|
|
||||||
{
|
|
||||||
get { return GetValue(SelectedItemProperty); }
|
|
||||||
set { SetValue(SelectedItemProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICommand PullToRefreshCommand
|
|
||||||
{
|
|
||||||
get { return (ICommand)GetValue(PullToRefreshCommandProperty); }
|
|
||||||
set { SetValue(PullToRefreshCommandProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRefreshing
|
|
||||||
{
|
|
||||||
get { return (bool)GetValue(IsRefreshingProperty); }
|
|
||||||
set { SetValue(IsRefreshingProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Thickness BorderThickness
|
|
||||||
{
|
|
||||||
get { return (Thickness)GetValue(BorderThicknessProperty); }
|
|
||||||
set { SetValue(BorderThicknessProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HeaderBordersVisible
|
|
||||||
{
|
|
||||||
get { return (bool)GetValue(HeaderBordersVisibleProperty); }
|
|
||||||
set { SetValue(HeaderBordersVisibleProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SortData SortedColumnIndex
|
|
||||||
{
|
|
||||||
get { return (SortData)GetValue(SortedColumnIndexProperty); }
|
|
||||||
set { SetValue(SortedColumnIndexProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Style HeaderLabelStyle
|
|
||||||
{
|
|
||||||
get { return (Style)GetValue(HeaderLabelStyleProperty); }
|
|
||||||
set { SetValue(HeaderLabelStyleProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageSource AscendingIcon
|
|
||||||
{
|
|
||||||
get { return (ImageSource)GetValue(AscendingIconProperty); }
|
|
||||||
set { SetValue(AscendingIconProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageSource DescendingIcon
|
|
||||||
{
|
|
||||||
get { return (ImageSource)GetValue(DescendingIconProperty); }
|
|
||||||
set { SetValue(DescendingIconProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Style AscendingIconStyle
|
|
||||||
{
|
|
||||||
get { return (Style)GetValue(AscendingIconStyleProperty); }
|
|
||||||
set { SetValue(AscendingIconStyleProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Style DescendingIconStyle
|
|
||||||
{
|
|
||||||
get { return (Style)GetValue(DescendingIconStyleProperty); }
|
|
||||||
set { SetValue(DescendingIconStyleProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public View NoDataView
|
|
||||||
{
|
|
||||||
get { return (View)GetValue(NoDataViewProperty); }
|
|
||||||
set { SetValue(NoDataViewProperty, value); }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region UI Methods
|
|
||||||
protected override void OnParentSet()
|
|
||||||
{
|
|
||||||
base.OnParentSet();
|
|
||||||
InitHeaderView();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBindingContextChanged()
|
|
||||||
{
|
|
||||||
base.OnBindingContextChanged();
|
|
||||||
SetColumnsBindingContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Private Methods
|
|
||||||
|
|
||||||
private void Reload()
|
|
||||||
{
|
|
||||||
InternalItems = new ObservableCollection<object>(_internalItems);
|
|
||||||
}
|
|
||||||
private void SortItems(SortData sData)
|
|
||||||
{
|
|
||||||
if (InternalItems == null || sData.Index >= Columns.Count || !Columns[sData.Index].SortingEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var items = InternalItems;
|
|
||||||
var column = Columns[sData.Index];
|
|
||||||
SortingOrder order = sData.Order;
|
|
||||||
|
|
||||||
if (!IsSortable)
|
|
||||||
throw new InvalidOperationException("This DataGrid is not sortable");
|
|
||||||
else if (column.PropertyName == null)
|
|
||||||
throw new InvalidOperationException("Please set the PropertyName property of Column");
|
|
||||||
|
|
||||||
//Sort
|
|
||||||
// if (order == SortingOrder.Descendant)
|
|
||||||
// items = items.OrderByDescending(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList();
|
|
||||||
// else
|
|
||||||
// items = items.OrderBy(x => ReflectionUtils.GetValueByPath(x, column.PropertyName)).ToList();
|
|
||||||
|
|
||||||
column.SortingIcon.Style = (order == SortingOrder.Descendant) ?
|
|
||||||
AscendingIconStyle ?? (Style)_headerView.Resources["DescendingIconStyle"] :
|
|
||||||
DescendingIconStyle ?? (Style)_headerView.Resources["AscendingIconStyle"];
|
|
||||||
|
|
||||||
//Support DescendingIcon property (if setted)
|
|
||||||
if (!column.SortingIcon.Style.Setters.Any(x => x.Property == Image.SourceProperty))
|
|
||||||
{
|
|
||||||
if (order == SortingOrder.Descendant && DescendingIconProperty.DefaultValue != DescendingIcon)
|
|
||||||
column.SortingIcon.Source = DescendingIcon;
|
|
||||||
if (order == SortingOrder.Ascendant && AscendingIconProperty.DefaultValue != AscendingIcon)
|
|
||||||
column.SortingIcon.Source = AscendingIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < Columns.Count; i++)
|
|
||||||
{
|
|
||||||
if (i != sData.Index)
|
|
||||||
{
|
|
||||||
if (Columns[i].SortingIcon.Style != null)
|
|
||||||
Columns[i].SortingIcon.Style = null;
|
|
||||||
if (Columns[i].SortingIcon.Source != null)
|
|
||||||
Columns[i].SortingIcon.Source = null;
|
|
||||||
_sortingOrders[i] = SortingOrder.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_internalItems = items;
|
|
||||||
|
|
||||||
_sortingOrders[sData.Index] = order;
|
|
||||||
SortedColumnIndex = sData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private View GetHeaderViewForColumn(DataGridColumn column)
|
|
||||||
{
|
|
||||||
column.HeaderLabel.Style = column.HeaderLabelStyle ?? this.HeaderLabelStyle ?? (Style)_headerView.Resources["HeaderDefaultStyle"];
|
|
||||||
|
|
||||||
Grid grid = new Grid
|
|
||||||
{
|
|
||||||
ColumnSpacing = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
|
||||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
|
||||||
|
|
||||||
if (IsSortable)
|
|
||||||
{
|
|
||||||
column.SortingIcon.Style = (Style)_headerView.Resources["ImageStyleBase"];
|
|
||||||
|
|
||||||
grid.Children.Add(column.SortingIcon);
|
|
||||||
Grid.SetColumn(column.SortingIcon, 1);
|
|
||||||
|
|
||||||
TapGestureRecognizer tgr = new TapGestureRecognizer();
|
|
||||||
tgr.Tapped += (s, e) =>
|
|
||||||
{
|
|
||||||
int index = Columns.IndexOf(column);
|
|
||||||
SortingOrder order = _sortingOrders[index] == SortingOrder.Ascendant ? SortingOrder.Descendant : SortingOrder.Ascendant;
|
|
||||||
|
|
||||||
if (Columns.ElementAt(index).SortingEnabled)
|
|
||||||
SortedColumnIndex = new SortData(index, order);
|
|
||||||
};
|
|
||||||
grid.GestureRecognizers.Add(tgr);
|
|
||||||
}
|
|
||||||
|
|
||||||
grid.Children.Add(column.HeaderLabel);
|
|
||||||
|
|
||||||
return grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitHeaderView()
|
|
||||||
{
|
|
||||||
SetColumnsBindingContext();
|
|
||||||
_headerView.Children.Clear();
|
|
||||||
_headerView.ColumnDefinitions.Clear();
|
|
||||||
_sortingOrders.Clear();
|
|
||||||
|
|
||||||
_headerView.Padding = new Thickness(BorderThickness.Left, BorderThickness.Top, BorderThickness.Right, 0);
|
|
||||||
_headerView.ColumnSpacing = BorderThickness.HorizontalThickness / 2;
|
|
||||||
|
|
||||||
if (Columns != null)
|
|
||||||
{
|
|
||||||
foreach (var col in Columns)
|
|
||||||
{
|
|
||||||
_headerView.ColumnDefinitions.Add(new ColumnDefinition { Width = col.Width });
|
|
||||||
|
|
||||||
var cell = GetHeaderViewForColumn(col);
|
|
||||||
|
|
||||||
_headerView.Children.Add(cell);
|
|
||||||
Grid.SetColumn(cell, Columns.IndexOf(col));
|
|
||||||
|
|
||||||
_sortingOrders.Add(Columns.IndexOf(col), SortingOrder.None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetColumnsBindingContext()
|
|
||||||
{
|
|
||||||
if (Columns != null)
|
|
||||||
foreach (var c in Columns)
|
|
||||||
c.BindingContext = BindingContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Private Methods
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public class DataGridColumn : BindableObject, IDefinition
|
|
||||||
{
|
|
||||||
#region bindable properties
|
|
||||||
public static readonly BindableProperty WidthProperty =
|
|
||||||
BindableProperty.Create(nameof(Width), typeof(GridLength), typeof(DataGridColumn), new GridLength(1, GridUnitType.Star),
|
|
||||||
propertyChanged: (bindable, oldValue, newValue) =>
|
|
||||||
{
|
|
||||||
if (oldValue != newValue)
|
|
||||||
{
|
|
||||||
(bindable as DataGridColumn).OnSizeChanged();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly BindableProperty TitleProperty =
|
|
||||||
BindableProperty.Create(nameof(Title), typeof(string), typeof(DataGridColumn), string.Empty,
|
|
||||||
propertyChanged: (b, o, n) => (b as DataGridColumn).HeaderLabel.Text = (string)n);
|
|
||||||
|
|
||||||
public static readonly BindableProperty FormattedTitleProperty =
|
|
||||||
BindableProperty.Create(nameof(FormattedTitle), typeof(FormattedString), typeof(DataGridColumn),
|
|
||||||
propertyChanged: (b, o, n) => (b as DataGridColumn).HeaderLabel.FormattedText = (FormattedString)n);
|
|
||||||
|
|
||||||
public static readonly BindableProperty PropertyNameProperty =
|
|
||||||
BindableProperty.Create(nameof(PropertyName), typeof(string), typeof(DataGridColumn), null);
|
|
||||||
|
|
||||||
public static readonly BindableProperty StringFormatProperty =
|
|
||||||
BindableProperty.Create(nameof(StringFormat), typeof(string), typeof(DataGridColumn), null);
|
|
||||||
|
|
||||||
public static readonly BindableProperty CellTemplateProperty =
|
|
||||||
BindableProperty.Create(nameof(CellTemplate), typeof(DataTemplate), typeof(DataGridColumn), null);
|
|
||||||
|
|
||||||
public static readonly BindableProperty HorizontalContentAlignmentProperty =
|
|
||||||
BindableProperty.Create(nameof(HorizontalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center);
|
|
||||||
|
|
||||||
public static readonly BindableProperty VerticalContentAlignmentProperty =
|
|
||||||
BindableProperty.Create(nameof(VerticalContentAlignment), typeof(LayoutOptions), typeof(DataGridColumn), LayoutOptions.Center);
|
|
||||||
|
|
||||||
public static readonly BindableProperty SortingEnabledProperty =
|
|
||||||
BindableProperty.Create(nameof(SortingEnabled), typeof(bool), typeof(DataGridColumn), true);
|
|
||||||
|
|
||||||
public static readonly BindableProperty HeaderLabelStyleProperty =
|
|
||||||
BindableProperty.Create(nameof(HeaderLabelStyle), typeof(Style), typeof(DataGridColumn),
|
|
||||||
propertyChanged: (b, o, n) =>
|
|
||||||
{
|
|
||||||
if ((b as DataGridColumn).HeaderLabel != null && (o != n))
|
|
||||||
(b as DataGridColumn).HeaderLabel.Style = n as Style;
|
|
||||||
});
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region properties
|
|
||||||
|
|
||||||
public GridLength Width
|
|
||||||
{
|
|
||||||
get { return (GridLength)GetValue(WidthProperty); }
|
|
||||||
set { SetValue(WidthProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Title
|
|
||||||
{
|
|
||||||
get { return (string)GetValue(TitleProperty); }
|
|
||||||
set { SetValue(TitleProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormattedString FormattedTitle
|
|
||||||
{
|
|
||||||
get { return (string)GetValue(FormattedTitleProperty); }
|
|
||||||
set { SetValue(FormattedTitleProperty, value); }
|
|
||||||
}
|
|
||||||
public string PropertyName
|
|
||||||
{
|
|
||||||
get { return (string)GetValue(PropertyNameProperty); }
|
|
||||||
set { SetValue(PropertyNameProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string StringFormat
|
|
||||||
{
|
|
||||||
get { return (string)GetValue(StringFormatProperty); }
|
|
||||||
set { SetValue(StringFormatProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataTemplate CellTemplate
|
|
||||||
{
|
|
||||||
get { return (DataTemplate)GetValue(CellTemplateProperty); }
|
|
||||||
set { SetValue(CellTemplateProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Image SortingIcon { get; set; }
|
|
||||||
internal Label HeaderLabel { get; set; }
|
|
||||||
|
|
||||||
public LayoutOptions HorizontalContentAlignment
|
|
||||||
{
|
|
||||||
get { return (LayoutOptions)GetValue(HorizontalContentAlignmentProperty); }
|
|
||||||
set { SetValue(HorizontalContentAlignmentProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutOptions VerticalContentAlignment
|
|
||||||
{
|
|
||||||
get { return (LayoutOptions)GetValue(VerticalContentAlignmentProperty); }
|
|
||||||
set { SetValue(VerticalContentAlignmentProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SortingEnabled
|
|
||||||
{
|
|
||||||
get { return (bool)GetValue(SortingEnabledProperty); }
|
|
||||||
set { SetValue(SortingEnabledProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Style HeaderLabelStyle
|
|
||||||
{
|
|
||||||
get { return (Style)GetValue(HeaderLabelStyleProperty); }
|
|
||||||
set { SetValue(HeaderLabelStyleProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public event EventHandler SizeChanged;
|
|
||||||
|
|
||||||
public DataGridColumn()
|
|
||||||
{
|
|
||||||
HeaderLabel = new Label();
|
|
||||||
SortingIcon = new Image();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnSizeChanged()
|
|
||||||
{
|
|
||||||
SizeChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using Xamarin.Forms;
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
internal class DataGridRowTemplateSelector : DataTemplateSelector
|
|
||||||
{
|
|
||||||
private static DataTemplate _dataGridRowTemplate;
|
|
||||||
|
|
||||||
public DataGridRowTemplateSelector()
|
|
||||||
{
|
|
||||||
_dataGridRowTemplate = new DataTemplate(typeof(DataGridViewCell));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
|
|
||||||
{
|
|
||||||
ListView listView = container as ListView;
|
|
||||||
DataGrid dataGrid = listView.Parent as DataGrid;
|
|
||||||
var items = dataGrid.InternalItems;
|
|
||||||
|
|
||||||
_dataGridRowTemplate.SetValue(DataGridViewCell.DataGridProperty, dataGrid);
|
|
||||||
_dataGridRowTemplate.SetValue(DataGridViewCell.RowContextProperty, item);
|
|
||||||
|
|
||||||
if (items != null)
|
|
||||||
{
|
|
||||||
_dataGridRowTemplate.SetValue(DataGridViewCell.IndexProperty, items.IndexOf(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
return _dataGridRowTemplate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,163 +0,0 @@
|
|||||||
using Xamarin.Forms;
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
internal sealed class DataGridViewCell : ViewCell
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
Grid _mainLayout;
|
|
||||||
Color _bgColor;
|
|
||||||
Color _textColor;
|
|
||||||
bool _hasSelected;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region properties
|
|
||||||
public DataGrid DataGrid
|
|
||||||
{
|
|
||||||
get { return (DataGrid)GetValue(DataGridProperty); }
|
|
||||||
set { SetValue(DataGridProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Index
|
|
||||||
{
|
|
||||||
get { return (int)GetValue(IndexProperty); }
|
|
||||||
set { SetValue(IndexProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public object RowContext
|
|
||||||
{
|
|
||||||
get { return GetValue(RowContextProperty); }
|
|
||||||
set { SetValue(RowContextProperty, value); }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Bindable Properties
|
|
||||||
public static readonly BindableProperty DataGridProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(DataGrid),
|
|
||||||
typeof(DataGrid),
|
|
||||||
typeof(DataGridViewCell),
|
|
||||||
null,
|
|
||||||
propertyChanged: (b, o, n) => (b as DataGridViewCell).CreateView());
|
|
||||||
|
|
||||||
public static readonly BindableProperty IndexProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(Index),
|
|
||||||
typeof(int),
|
|
||||||
typeof(DataGridViewCell),
|
|
||||||
0,
|
|
||||||
propertyChanged: (b, o, n) => (b as DataGridViewCell).UpdateBackgroundColor());
|
|
||||||
|
|
||||||
public static readonly BindableProperty RowContextProperty =
|
|
||||||
BindableProperty.Create(
|
|
||||||
nameof(RowContext),
|
|
||||||
typeof(object),
|
|
||||||
typeof(DataGridViewCell),
|
|
||||||
propertyChanged: (b, o, n) => (b as DataGridViewCell).UpdateBackgroundColor());
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
private void CreateView()
|
|
||||||
{
|
|
||||||
UpdateBackgroundColor();
|
|
||||||
|
|
||||||
_mainLayout = new Grid()
|
|
||||||
{
|
|
||||||
BackgroundColor = DataGrid.BorderColor,
|
|
||||||
RowSpacing = 0,
|
|
||||||
ColumnSpacing = DataGrid.BorderThickness.HorizontalThickness / 2,
|
|
||||||
Padding = new Thickness(DataGrid.BorderThickness.HorizontalThickness / 2,
|
|
||||||
DataGrid.BorderThickness.VerticalThickness / 2),
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var col in DataGrid.Columns)
|
|
||||||
{
|
|
||||||
_mainLayout.ColumnDefinitions.Add(new ColumnDefinition() { Width = col.Width });
|
|
||||||
View cell;
|
|
||||||
|
|
||||||
if (col.CellTemplate != null)
|
|
||||||
{
|
|
||||||
cell = new ContentView() { Content = col.CellTemplate.CreateContent() as View };
|
|
||||||
if (col.PropertyName != null)
|
|
||||||
{
|
|
||||||
cell.SetBinding(BindingContextProperty,
|
|
||||||
new Binding(col.PropertyName, source: RowContext));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var text = new Label
|
|
||||||
{
|
|
||||||
TextColor = _textColor,
|
|
||||||
HorizontalOptions = col.HorizontalContentAlignment,
|
|
||||||
VerticalOptions = col.VerticalContentAlignment,
|
|
||||||
LineBreakMode = LineBreakMode.WordWrap,
|
|
||||||
};
|
|
||||||
text.SetBinding(Label.TextProperty, new Binding(col.PropertyName, BindingMode.Default, stringFormat: col.StringFormat));
|
|
||||||
text.SetBinding(Label.FontSizeProperty, new Binding(DataGrid.FontSizeProperty.PropertyName, BindingMode.Default, source: DataGrid));
|
|
||||||
text.SetBinding(Label.FontFamilyProperty, new Binding(DataGrid.FontFamilyProperty.PropertyName, BindingMode.Default, source: DataGrid));
|
|
||||||
|
|
||||||
cell = new ContentView
|
|
||||||
{
|
|
||||||
Padding = 0,
|
|
||||||
BackgroundColor = _bgColor,
|
|
||||||
Content = text,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_mainLayout.Children.Add(cell);
|
|
||||||
Grid.SetColumn(cell, DataGrid.Columns.IndexOf(col));
|
|
||||||
}
|
|
||||||
|
|
||||||
View = _mainLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateBackgroundColor()
|
|
||||||
{
|
|
||||||
_hasSelected = DataGrid.SelectedItem == RowContext;
|
|
||||||
int actualIndex = DataGrid?.InternalItems?.IndexOf(BindingContext) ?? -1;
|
|
||||||
if (actualIndex > -1)
|
|
||||||
{
|
|
||||||
_bgColor = (DataGrid.SelectionEnabled && DataGrid.SelectedItem != null && DataGrid.SelectedItem == RowContext) ?
|
|
||||||
DataGrid.ActiveRowColor : DataGrid.RowsBackgroundColorPalette.GetColor(Index, BindingContext);
|
|
||||||
_textColor = DataGrid.RowsTextColorPalette.GetColor(actualIndex, BindingContext);
|
|
||||||
|
|
||||||
ChangeColor(_bgColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ChangeColor(Color color)
|
|
||||||
{
|
|
||||||
foreach (var v in _mainLayout.Children)
|
|
||||||
{
|
|
||||||
v.BackgroundColor = color;
|
|
||||||
var contentView = v as ContentView;
|
|
||||||
if (contentView?.Content is Label)
|
|
||||||
((Label)contentView.Content).TextColor = _textColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBindingContextChanged()
|
|
||||||
{
|
|
||||||
base.OnBindingContextChanged();
|
|
||||||
UpdateBackgroundColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnParentSet()
|
|
||||||
{
|
|
||||||
base.OnParentSet();
|
|
||||||
if (Parent != null)
|
|
||||||
DataGrid.ItemSelected += DataGrid_ItemSelected;
|
|
||||||
else
|
|
||||||
DataGrid.ItemSelected -= DataGrid_ItemSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DataGrid_ItemSelected(object sender, SelectedItemChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (DataGrid.SelectionEnabled && (e.SelectedItem == RowContext || _hasSelected))
|
|
||||||
{
|
|
||||||
UpdateBackgroundColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
using Xamarin.Forms;
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public interface IColorProvider
|
|
||||||
{
|
|
||||||
Color GetColor(int rowIndex, object item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public sealed class PaletteCollection : List<Color>, IColorProvider
|
|
||||||
{
|
|
||||||
public Color GetColor(int rowIndex, object item)
|
|
||||||
{
|
|
||||||
if (Count > 0)
|
|
||||||
return this.ElementAt(rowIndex % Count);
|
|
||||||
else
|
|
||||||
return default(Color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
|
|
||||||
[TypeConverter(typeof(SortDataTypeConverter))]
|
|
||||||
public class SortData
|
|
||||||
{
|
|
||||||
|
|
||||||
#region ctor
|
|
||||||
public SortData()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SortData(int index, SortingOrder order)
|
|
||||||
{
|
|
||||||
Index = index;
|
|
||||||
Order = order;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public SortingOrder Order { get; set; }
|
|
||||||
|
|
||||||
public int Index { get; set; }
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public static implicit operator SortData(int index)
|
|
||||||
{
|
|
||||||
return new SortData
|
|
||||||
{
|
|
||||||
Index = Math.Abs(index),
|
|
||||||
Order = index < 0 ? SortingOrder.Descendant : SortingOrder.Ascendant
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is SortData)
|
|
||||||
{
|
|
||||||
SortData other = obj as SortData;
|
|
||||||
return other.Index == Index && other.Order == Order;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public class SortDataTypeConverter : TypeConverter
|
|
||||||
{
|
|
||||||
|
|
||||||
public override bool CanConvertFrom(Type sourceType)
|
|
||||||
{
|
|
||||||
return base.CanConvertFrom(sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object ConvertFromInvariantString(string value)
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (int.TryParse(value, out index))
|
|
||||||
return (SortData)index;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
namespace Aurora.Design.Components.DataGrid
|
|
||||||
{
|
|
||||||
public enum SortingOrder
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Ascendant = 1,
|
|
||||||
Descendant = 2,
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.9 KiB |
@ -1,577 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Linq;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
using Aurora.Proto.Party;
|
|
||||||
using Aurora.Models.Media;
|
|
||||||
using Aurora.Services.Client;
|
|
||||||
using Aurora.Design.Views.Party.NewPartyDialog;
|
|
||||||
using Aurora.Services.Settings;
|
|
||||||
using Aurora.Services.Server;
|
|
||||||
using Aurora.Services.EventManager;
|
|
||||||
using Grpc.Core;
|
|
||||||
|
|
||||||
namespace Aurora.Design.Views.Party
|
|
||||||
{
|
|
||||||
//TODO refactor
|
|
||||||
enum PartyState
|
|
||||||
{
|
|
||||||
SelectingHost,
|
|
||||||
InParty,
|
|
||||||
Hosting,
|
|
||||||
Connecting,
|
|
||||||
}
|
|
||||||
delegate void EventHandler(BaseEvent e);
|
|
||||||
public class PartyViewModel : BaseViewModel
|
|
||||||
{
|
|
||||||
private PartyState _state;
|
|
||||||
private string _hostname = "";
|
|
||||||
private ObservableCollection<Member> _members;
|
|
||||||
private ObservableCollection<BaseMedia> _queue;
|
|
||||||
private BaseMedia _selectedMedia;
|
|
||||||
private ISettingsService _settingsService;
|
|
||||||
private IClientService _clientService;
|
|
||||||
private IServerService _serverService;
|
|
||||||
private IEventManager _eventManager;
|
|
||||||
|
|
||||||
private CancellationTokenSource _eventCancellationTokenSource;
|
|
||||||
|
|
||||||
private Dictionary<BaseEvent.DerivedEventOneofCase, EventHandler> _eventHandlers;
|
|
||||||
|
|
||||||
private int _selectedTabIndex;
|
|
||||||
|
|
||||||
public PartyViewModel(
|
|
||||||
ISettingsService settingsService,
|
|
||||||
IServerService serverService,
|
|
||||||
IEventManager eventManager,
|
|
||||||
IClientService clientService)
|
|
||||||
{
|
|
||||||
_members = new ObservableCollection<Member>();
|
|
||||||
_queue = new ObservableCollection<BaseMedia>();
|
|
||||||
|
|
||||||
this._settingsService = settingsService;
|
|
||||||
this._serverService = serverService;
|
|
||||||
this._eventManager = eventManager;
|
|
||||||
this._clientService = clientService;
|
|
||||||
|
|
||||||
SetState(PartyState.SelectingHost);
|
|
||||||
|
|
||||||
PlayCommand = new Command(OnDoubleClickCommandExecute, CanDoubleClickCommandExecute);
|
|
||||||
|
|
||||||
LeavePartyCommand = new Command(OnLeavePartyCommandExecute, CanLeavePartyCommandExecute);
|
|
||||||
|
|
||||||
//Setup event handlers
|
|
||||||
_eventHandlers = new Dictionary<BaseEvent.DerivedEventOneofCase, EventHandler>()
|
|
||||||
{
|
|
||||||
{BaseEvent.DerivedEventOneofCase.MediaPausedEvent, this.OnRemoteMediaPaused},
|
|
||||||
{BaseEvent.DerivedEventOneofCase.MediaResumedEvent, this.OnRemoteMediaResumed},
|
|
||||||
{BaseEvent.DerivedEventOneofCase.NewMediaPlayingEvent, this.OnNewRemoteMediaPlaying},
|
|
||||||
{BaseEvent.DerivedEventOneofCase.MemberCreatedEvent, this.OnPartyMemberJoined},
|
|
||||||
{BaseEvent.DerivedEventOneofCase.MemberDeletedEvent, this.OnPartyMemberLeft}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
public int SelectedTabIndex
|
|
||||||
{
|
|
||||||
get { return _selectedTabIndex; }
|
|
||||||
set { SetProperty(ref _selectedTabIndex, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Publc property for the members list
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public ObservableCollection<Member> Members
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _members;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _members, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Public property for queue item source
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public ObservableCollection<BaseMedia> Queue
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _queue;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != _queue)
|
|
||||||
{
|
|
||||||
SetProperty(ref _queue, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Public property for the currently selected song.
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public BaseMedia SelectedSong
|
|
||||||
{
|
|
||||||
get { return _selectedMedia; }
|
|
||||||
set { SetProperty(ref _selectedMedia, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Public property for playing media
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public Command PlayCommand { get; private set; }
|
|
||||||
|
|
||||||
public Command LeavePartyCommand { get; private set; }
|
|
||||||
|
|
||||||
#endregion Properties
|
|
||||||
|
|
||||||
#region Events
|
|
||||||
/// <summary>
|
|
||||||
/// Called by framework when view becomes active
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override async Task OnActive()
|
|
||||||
{
|
|
||||||
OnPropertyChanged("SelectedTabIndex");
|
|
||||||
if (this._state == PartyState.Hosting ||
|
|
||||||
this._state == PartyState.InParty)
|
|
||||||
{
|
|
||||||
await this.GetEvents().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Open host selection modal
|
|
||||||
NewPartyDialogViewModel vm = new NewPartyDialogViewModel();
|
|
||||||
ConnectionDetails details = new ConnectionDetails();
|
|
||||||
vm.Finish = () =>
|
|
||||||
{
|
|
||||||
this.HideModal();
|
|
||||||
details = vm.ReturnObject as ConnectionDetails;
|
|
||||||
_hostname = details.HostName;
|
|
||||||
switch (details.ConnectionType)
|
|
||||||
{
|
|
||||||
case ConnectionType.Host:
|
|
||||||
{
|
|
||||||
OnHostCommandExecute();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ConnectionType.Join:
|
|
||||||
{
|
|
||||||
OnJoinCommandExecute();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.ShowModal(typeof(NewPartyDialog.NewPartyDialog), vm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called by framework when view becomes inactive
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override Task OnInactive()
|
|
||||||
{
|
|
||||||
if(this._eventCancellationTokenSource != null){
|
|
||||||
this._eventCancellationTokenSource.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.FromResult<object>(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remote media paused event
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
public void OnRemoteMediaPaused(BaseEvent e)
|
|
||||||
{
|
|
||||||
StopPlaying();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remote playing new media event
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
public void OnNewRemoteMediaPlaying(BaseEvent e)
|
|
||||||
{
|
|
||||||
PlayFromBeginning(GetMediaFromQueue(e.NewMediaPlayingEvent.Media.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remote resumed playing event
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
public void OnRemoteMediaResumed(BaseEvent e)
|
|
||||||
{
|
|
||||||
PlayResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Member joined party event
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
public void OnPartyMemberJoined(BaseEvent e)
|
|
||||||
{
|
|
||||||
Members.Add(e.MemberCreatedEvent.Member);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Member left party event
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
public void OnPartyMemberLeft(BaseEvent e)
|
|
||||||
{
|
|
||||||
var found = Members.Where(x => x.Name == e.MemberDeletedEvent.MemberName);
|
|
||||||
foreach (Member member in found)
|
|
||||||
{
|
|
||||||
_members.Remove(member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Events
|
|
||||||
|
|
||||||
#region Commands
|
|
||||||
private async void OnJoinCommandExecute()
|
|
||||||
{
|
|
||||||
SetState(PartyState.Connecting);
|
|
||||||
_clientService.Start(_hostname, this._settingsService.DefaultPort.ToString());
|
|
||||||
await JoinParty(false);
|
|
||||||
|
|
||||||
//TODO add cancellation token
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SetState(PartyState.InParty);
|
|
||||||
await GetEvents().ConfigureAwait(true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Exception occurred while receiviing events: ", ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CanJoinCommandExecute()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnHostCommandExecute()
|
|
||||||
{
|
|
||||||
//Change state
|
|
||||||
SetState(PartyState.Connecting);
|
|
||||||
_serverService.Start("test", "asdf");
|
|
||||||
string localHost = ServerService.GetLocalIPAddress();
|
|
||||||
_clientService.Start(localHost, this._settingsService.DefaultPort.ToString());
|
|
||||||
await JoinParty(true);
|
|
||||||
|
|
||||||
|
|
||||||
//TODO add cancellation token
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SetState(PartyState.Hosting);
|
|
||||||
await GetEvents().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Exception occurred while receiviing events: ", ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CanHostCommandExecute()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void OnLeavePartyCommandExecute()
|
|
||||||
{
|
|
||||||
await _clientService.RemotePartyServiceClient.DeleteMemberAsync(new DeleteMemberRequest()
|
|
||||||
{
|
|
||||||
Name = _settingsService.ClientName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CanLeavePartyCommandExecute()
|
|
||||||
{
|
|
||||||
return (this._state == PartyState.InParty || this._state == PartyState.Hosting) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnPlayButtonCommandExecute()
|
|
||||||
{
|
|
||||||
if (base.IsPlaying())
|
|
||||||
{
|
|
||||||
//Fire play stopped event
|
|
||||||
AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata;
|
|
||||||
MediaPausedEvent mediaPaused = new MediaPausedEvent();
|
|
||||||
|
|
||||||
_eventManager.FireEvent(new BaseEvent()
|
|
||||||
{
|
|
||||||
MediaPausedEvent = mediaPaused
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Fire play resume event
|
|
||||||
AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata;
|
|
||||||
MediaResumedEvent mediaResumed = new MediaResumedEvent();
|
|
||||||
|
|
||||||
_eventManager.FireEvent(new BaseEvent()
|
|
||||||
{
|
|
||||||
MediaResumedEvent = mediaResumed
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanPlayButtonCommandExecute()
|
|
||||||
{
|
|
||||||
return this._state == PartyState.Hosting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanNextButtonCommandExecute()
|
|
||||||
{
|
|
||||||
return this._state == PartyState.Hosting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanPreviousButtonCommandExecute()
|
|
||||||
{
|
|
||||||
return this._state == PartyState.Hosting;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// On double click execute, fire media playing event
|
|
||||||
/// </summary>
|
|
||||||
public void OnDoubleClickCommandExecute()
|
|
||||||
{
|
|
||||||
//Fire Playing event
|
|
||||||
AudioMetadata meta = _selectedMedia.Metadata as AudioMetadata;
|
|
||||||
NewMediaPlayingEvent mediaPlaying = new NewMediaPlayingEvent()
|
|
||||||
{
|
|
||||||
Media = new Media()
|
|
||||||
{
|
|
||||||
//TODO need full resource name
|
|
||||||
Name = _selectedMedia.Id,
|
|
||||||
Title = meta.Title,
|
|
||||||
Artist = meta.Artist,
|
|
||||||
Album = meta.Album,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_eventManager.FireEvent(new BaseEvent()
|
|
||||||
{
|
|
||||||
NewMediaPlayingEvent = mediaPlaying
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanDoubleClickCommandExecute()
|
|
||||||
{
|
|
||||||
return this._state == PartyState.Hosting;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion Commands
|
|
||||||
|
|
||||||
#region Private Methods
|
|
||||||
/// <summary>
|
|
||||||
/// Join the remote party.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task JoinParty(bool asHost)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Member resp = await _clientService.RemotePartyServiceClient.CreateMemberAsync(new CreateMemberRequest
|
|
||||||
{
|
|
||||||
Member = new Member()
|
|
||||||
{
|
|
||||||
UserName = this._settingsService.Username,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this._settingsService.ClientName = resp.Name;
|
|
||||||
|
|
||||||
await RefreshMembers();
|
|
||||||
|
|
||||||
//Subscribe to events
|
|
||||||
await SubscribeToEvents();
|
|
||||||
|
|
||||||
Queue.Clear();
|
|
||||||
|
|
||||||
ListMediaResponse mediaResponse = await _clientService.RemotePartyServiceClient.ListMediaAsync(new ListMediaRequest()
|
|
||||||
{
|
|
||||||
PageSize = 50,
|
|
||||||
Parent = "TODO"
|
|
||||||
});
|
|
||||||
|
|
||||||
//Convert received data to remote audio models
|
|
||||||
foreach (Media data in mediaResponse.Media)
|
|
||||||
{
|
|
||||||
//Assign received metadata (since this can't be aquired from a file)
|
|
||||||
AudioMetadata meta = new AudioMetadata();
|
|
||||||
meta.Title = data.Title;
|
|
||||||
meta.Album = data.Album;
|
|
||||||
meta.Artist = data.Artist;
|
|
||||||
meta.Duration = data.Duration;
|
|
||||||
|
|
||||||
RemoteAudio remote = new RemoteAudio(data.Name,
|
|
||||||
asHost,
|
|
||||||
meta,
|
|
||||||
_clientService.RemotePartyServiceClient);
|
|
||||||
|
|
||||||
Queue.Add(remote);
|
|
||||||
OnPropertyChanged("Queue");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Error subscribing to events: " + ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LeaveParty()
|
|
||||||
{
|
|
||||||
//Stop receiving events
|
|
||||||
// _client.StopEvents();
|
|
||||||
|
|
||||||
//Unsubscribe
|
|
||||||
await UnsubscribeFromEvents();
|
|
||||||
|
|
||||||
//Leave party
|
|
||||||
DeleteMemberRequest req = new DeleteMemberRequest()
|
|
||||||
{
|
|
||||||
Name = _settingsService.ClientName
|
|
||||||
};
|
|
||||||
|
|
||||||
await _clientService.RemotePartyServiceClient.DeleteMemberAsync(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SubscribeToEvents()
|
|
||||||
{
|
|
||||||
CreateEventSubscriptionListRequest req = new CreateEventSubscriptionListRequest();
|
|
||||||
req.Parent = this._settingsService.ClientName;
|
|
||||||
req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MemberCreated });
|
|
||||||
req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MemberDeleted });
|
|
||||||
req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MediaPlaying });
|
|
||||||
req.EventSubscriptions.Add(new EventSubscription() { Type = EventType.MediaStopped });
|
|
||||||
|
|
||||||
Console.WriteLine(string.Format("CLIENT {0} - SubscribeToEvents called from client with id", this._settingsService.ClientName));
|
|
||||||
await _clientService.RemotePartyServiceClient.CreateEventSubscriptionListAsync(req);
|
|
||||||
}
|
|
||||||
private async Task UnsubscribeFromEvents()
|
|
||||||
{
|
|
||||||
DeleteAllEventSubscriptionsRequest unsubscribeReq = new DeleteAllEventSubscriptionsRequest();
|
|
||||||
await _clientService.RemotePartyServiceClient.DeleteAllEventSubscriptionsAsync(unsubscribeReq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Refresh members list.
|
|
||||||
/// </summary>
|
|
||||||
private async Task RefreshMembers()
|
|
||||||
{
|
|
||||||
Members.Clear();
|
|
||||||
ListMembersResponse response = await _clientService.RemotePartyServiceClient.ListMembersAsync(
|
|
||||||
new ListMembersRequest()
|
|
||||||
{
|
|
||||||
Parent = "TODO",
|
|
||||||
PageSize = 50,
|
|
||||||
});
|
|
||||||
//Add members
|
|
||||||
foreach (Member member in response.Members)
|
|
||||||
{
|
|
||||||
Members.Add(member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetState(PartyState state)
|
|
||||||
{
|
|
||||||
_state = state;
|
|
||||||
OnPropertyChanged("IsSelectingHost");
|
|
||||||
OnPropertyChanged("IsNotSelectingHost");
|
|
||||||
}
|
|
||||||
|
|
||||||
private BaseMedia GetMediaFromQueue(string Id)
|
|
||||||
{
|
|
||||||
if (_queue.Any((BaseMedia media) => media.Id == Id))
|
|
||||||
{
|
|
||||||
BaseMedia media = _queue.First((BaseMedia med) => med.Id == Id);
|
|
||||||
return media;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void PlayFromBeginning(BaseMedia args)
|
|
||||||
{
|
|
||||||
base.ChangePlayerState(args, Main.PlayAction.Play);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PlayResume()
|
|
||||||
{
|
|
||||||
base.ChangePlayerState(null, Main.PlayAction.Resume);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopPlaying()
|
|
||||||
{
|
|
||||||
base.ChangePlayerState(null, Main.PlayAction.Pause);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Asynchronous function for processing events off of the event stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task GetEvents()
|
|
||||||
{
|
|
||||||
_eventCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
string clientName = this._settingsService.ClientName;
|
|
||||||
Console.WriteLine(string.Format("CLIENT {0} - GetEvents called from client with id", clientName));
|
|
||||||
using (AsyncServerStreamingCall<BaseEvent> eventStream = _clientService.RemotePartyServiceClient
|
|
||||||
.GetEvents(new GetEventsRequest { Parent = this._settingsService.ClientName }))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!_eventCancellationTokenSource.Token.IsCancellationRequested &&
|
|
||||||
await eventStream.ResponseStream.MoveNext(_eventCancellationTokenSource.Token))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
BaseEvent e = new BaseEvent(eventStream.ResponseStream.Current);
|
|
||||||
|
|
||||||
_eventHandlers.TryGetValue(e.DerivedEventCase, out EventHandler handler);
|
|
||||||
|
|
||||||
if (handler != null && handler != null)
|
|
||||||
{
|
|
||||||
handler.Invoke(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Exception while parsing event ---" + ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(string.Format("EXCEPTION while parsing events --- " + ex.Message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion Private Methods
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Aurora.Cursor;
|
||||||
|
|
||||||
namespace Aurora.Proto.Party
|
namespace Aurora.Proto.Party
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Partial PartyMember class with a constructor that generates a new id
|
/// Partial PartyMember class with a constructor that generates a new id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class Member
|
public partial class Member : ICursorObject
|
||||||
{
|
{
|
||||||
public Member(string id)
|
public Member(string id)
|
||||||
{
|
{
|
@ -1,46 +0,0 @@
|
|||||||
using Grpc.Core;
|
|
||||||
using Aurora.Proto.Party;
|
|
||||||
using Aurora.Services.Settings;
|
|
||||||
|
|
||||||
namespace Aurora.Services.Client
|
|
||||||
{
|
|
||||||
|
|
||||||
public class ClientService : IClientService
|
|
||||||
{
|
|
||||||
private RemotePartyService.RemotePartyServiceClient _remotePartyClient;
|
|
||||||
|
|
||||||
private Channel _channel;
|
|
||||||
private ISettingsService _settingsService;
|
|
||||||
|
|
||||||
public ClientService(ISettingsService settingsService)
|
|
||||||
{
|
|
||||||
this._settingsService = settingsService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsStarted
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _remotePartyClient != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RemotePartyService.RemotePartyServiceClient RemotePartyServiceClient
|
|
||||||
{
|
|
||||||
get { return this._remotePartyClient; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start(string hostname, string port)
|
|
||||||
{
|
|
||||||
_channel = new Channel(string.Format("{0}:{1}", hostname, port), ChannelCredentials.Insecure);
|
|
||||||
|
|
||||||
_remotePartyClient = new RemotePartyService.RemotePartyServiceClient(_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Close()
|
|
||||||
{
|
|
||||||
await _channel.ShutdownAsync();
|
|
||||||
_remotePartyClient = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
using Aurora.Proto.Party;
|
|
||||||
|
|
||||||
namespace Aurora.Services.Client
|
|
||||||
{
|
|
||||||
public interface IClientService
|
|
||||||
{
|
|
||||||
bool IsStarted { get; }
|
|
||||||
|
|
||||||
RemotePartyService.RemotePartyServiceClient RemotePartyServiceClient { get; }
|
|
||||||
|
|
||||||
void Start(string hostname, string port);
|
|
||||||
|
|
||||||
void Close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,9 +6,10 @@ using Aurora.Services.Library;
|
|||||||
using Aurora.Services.Settings;
|
using Aurora.Services.Settings;
|
||||||
using Aurora.Models.Media;
|
using Aurora.Models.Media;
|
||||||
using Aurora.Services.EventManager;
|
using Aurora.Services.EventManager;
|
||||||
using Autofac;
|
using Aurora.Utils;
|
||||||
|
using Aurora.Cursor;
|
||||||
|
|
||||||
namespace Aurora.Services.Server.Controllers
|
namespace Aurora.Services.Controllers
|
||||||
{
|
{
|
||||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||||
{
|
{
|
||||||
@ -24,7 +25,7 @@ namespace Aurora.Services.Server.Controllers
|
|||||||
this._startDateTime = DateTime.UtcNow;
|
this._startDateTime = DateTime.UtcNow;
|
||||||
this._displayName = partyName;
|
this._displayName = partyName;
|
||||||
this._description = description;
|
this._description = description;
|
||||||
this._memberList = new SortedList<string, Member>();
|
this._memberList = new CursorList<Member>();
|
||||||
this._mediaList = new SortedList<string, Media>();
|
this._mediaList = new SortedList<string, Media>();
|
||||||
|
|
||||||
_libraryService = libraryService;
|
_libraryService = libraryService;
|
||||||
@ -36,9 +37,9 @@ namespace Aurora.Services.Server.Controllers
|
|||||||
|
|
||||||
this._hostMember = new Member()
|
this._hostMember = new Member()
|
||||||
{
|
{
|
||||||
Name = GetNewMemberResourceName(_partyResourceName, ServerService.GetLocalIPAddress(), userName),
|
Name = GetNewMemberResourceName(_partyResourceName, IpUtil.GetLocalIPAddress(), userName),
|
||||||
UserName = userName,
|
UserName = userName,
|
||||||
IpAddress = ServerService.GetLocalIPAddress(),
|
IpAddress = IpUtil.GetLocalIPAddress(),
|
||||||
};
|
};
|
||||||
|
|
||||||
//Add media from library
|
//Add media from library
|
@ -4,7 +4,7 @@ using System.Threading;
|
|||||||
using Aurora.Proto.Party;
|
using Aurora.Proto.Party;
|
||||||
using Aurora.Utils;
|
using Aurora.Utils;
|
||||||
|
|
||||||
namespace Aurora.Services.Server.Controllers
|
namespace Aurora.Services.Controllers
|
||||||
{
|
{
|
||||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||||
{
|
{
|
@ -5,7 +5,7 @@ using Aurora.Proto.Party;
|
|||||||
using Aurora.Proto.General;
|
using Aurora.Proto.General;
|
||||||
using Aurora.Utils;
|
using Aurora.Utils;
|
||||||
|
|
||||||
namespace Aurora.Services.Server.Controllers
|
namespace Aurora.Services.Controllers
|
||||||
{
|
{
|
||||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||||
{
|
{
|
@ -8,7 +8,7 @@ using Aurora.Services.Library;
|
|||||||
using Aurora.Services.Player;
|
using Aurora.Services.Player;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
|
|
||||||
namespace Aurora.Services.Server.Controllers
|
namespace Aurora.Services.Controllers
|
||||||
{
|
{
|
||||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||||
{
|
{
|
@ -6,40 +6,50 @@ using Aurora.Proto.General;
|
|||||||
using Aurora.Utils;
|
using Aurora.Utils;
|
||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using Google.Protobuf.WellKnownTypes;
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
using Aurora.Cursor;
|
||||||
|
|
||||||
namespace Aurora.Services.Server.Controllers
|
namespace Aurora.Services.Controllers
|
||||||
{
|
{
|
||||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||||
{
|
{
|
||||||
private SortedList<string, Member> _memberList;
|
private CursorList<Member> _memberList;
|
||||||
|
|
||||||
|
public CursorList<Member> MemberList
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this._memberList;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(this._memberList != value)
|
||||||
|
{
|
||||||
|
_memberList = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override Task<ListMembersResponse> ListMembers(ListMembersRequest request, Grpc.Core.ServerCallContext context)
|
public override Task<ListMembersResponse> ListMembers(ListMembersRequest request, Grpc.Core.ServerCallContext context)
|
||||||
{
|
{
|
||||||
|
Cursor<Member> cursor = new Cursor<Member>(ref this._memberList);
|
||||||
|
|
||||||
|
Aurora.Cursor.SortDirection direction = Aurora.Cursor.SortDirection.Asc;
|
||||||
|
|
||||||
|
CursorResult<Member> res = cursor
|
||||||
|
.WithNextPageToken(request.PageToken)
|
||||||
|
.WithSize(request.PageSize)
|
||||||
|
.GetNextPage();
|
||||||
|
|
||||||
//Ignoring parent field because there is only one instance of the party
|
//Ignoring parent field because there is only one instance of the party
|
||||||
ListMembersResponse resp = new ListMembersResponse();
|
ListMembersResponse resp = new ListMembersResponse();
|
||||||
|
|
||||||
//Determine start idx
|
resp.Members.AddRange(res.Result.ConvertAll(member => new Member()
|
||||||
int startIdx = 0;
|
|
||||||
if (!string.IsNullOrEmpty(request.PageToken))
|
|
||||||
{
|
{
|
||||||
startIdx = _memberList.IndexOfKey(request.PageToken) + 1;
|
Name = member.Name,
|
||||||
}
|
UserName = member.UserName,
|
||||||
|
IpAddress = member.IpAddress,
|
||||||
int pageSize = request.PageSize;
|
AddedOn = member.AddedOn
|
||||||
|
}));
|
||||||
//Assign pageSize
|
|
||||||
if (pageSize > _memberList.Count)
|
|
||||||
{
|
|
||||||
pageSize = _memberList.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Gather page
|
|
||||||
List<Member> members = new List<Member>(_memberList.Values);
|
|
||||||
resp.Members.AddRange(members.GetRange(startIdx, pageSize));
|
|
||||||
|
|
||||||
//Set next page token
|
|
||||||
resp.NextPageToken = resp.Members[resp.Members.Count - 1].Name;
|
|
||||||
|
|
||||||
return Task.FromResult(resp);
|
return Task.FromResult(resp);
|
||||||
}
|
}
|
||||||
@ -76,7 +86,7 @@ namespace Aurora.Services.Server.Controllers
|
|||||||
request.Member.AddedOn = Timestamp.FromDateTime(DateTime.UtcNow);
|
request.Member.AddedOn = Timestamp.FromDateTime(DateTime.UtcNow);
|
||||||
request.Member.IpAddress = context.Host;
|
request.Member.IpAddress = context.Host;
|
||||||
|
|
||||||
_memberList.Add(resourceName, request.Member);
|
_memberList.Add(request.Member);
|
||||||
|
|
||||||
BaseEvent @event = new BaseEvent
|
BaseEvent @event = new BaseEvent
|
||||||
{
|
{
|
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
using Aurora.Utils;
|
||||||
using Aurora.Proto.Party;
|
using Aurora.Proto.Party;
|
||||||
using Google.Protobuf.WellKnownTypes;
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
|
||||||
|
|
||||||
namespace Aurora.Services.Server.Controllers
|
namespace Aurora.Services.Controllers
|
||||||
{
|
{
|
||||||
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
public partial class RemotePartyController : RemotePartyService.RemotePartyServiceBase
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ namespace Aurora.Services.Server.Controllers
|
|||||||
Name = _partyResourceName,
|
Name = _partyResourceName,
|
||||||
DisplayName = this._displayName,
|
DisplayName = this._displayName,
|
||||||
Description = this._description,
|
Description = this._description,
|
||||||
HostIp = ServerService.GetLocalIPAddress(),
|
HostIp = IpUtil.GetLocalIPAddress(),
|
||||||
HostMember = this._hostMember,
|
HostMember = this._hostMember,
|
||||||
CreatedOn = Timestamp.FromDateTime(_startDateTime)
|
CreatedOn = Timestamp.FromDateTime(_startDateTime)
|
||||||
};
|
};
|
19
aurora-sharp-desktop/Aurora/Services/Global.cs
Normal file
19
aurora-sharp-desktop/Aurora/Services/Global.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace Aurora.Services
|
||||||
|
{
|
||||||
|
public enum PartyState
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
SelectingHost,
|
||||||
|
InParty,
|
||||||
|
Hosting,
|
||||||
|
Connecting,
|
||||||
|
}
|
||||||
|
public class Global
|
||||||
|
{
|
||||||
|
public Global()
|
||||||
|
{
|
||||||
|
this.State = PartyState.Idle;
|
||||||
|
}
|
||||||
|
public PartyState State {get; set;}
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Aurora.Services.Server
|
|
||||||
{
|
|
||||||
public interface IServerService
|
|
||||||
{
|
|
||||||
int Port { get; }
|
|
||||||
|
|
||||||
string Hostname { get; }
|
|
||||||
|
|
||||||
bool Initialized { get; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start Server
|
|
||||||
/// </summary>
|
|
||||||
void Start(string partyName, string description);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shutdown server async.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task</returns>
|
|
||||||
Task Stop();
|
|
||||||
|
|
||||||
Task Reset();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using Grpc.Core;
|
|
||||||
using Aurora.Services.Server.Controllers;
|
|
||||||
using Aurora.Services.Settings;
|
|
||||||
using Aurora.Services.Library;
|
|
||||||
using Aurora.Services.EventManager;
|
|
||||||
using Aurora.Proto.Party;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Aurora.Services.Server
|
|
||||||
{
|
|
||||||
public class ServerService : IServerService
|
|
||||||
{
|
|
||||||
private int _port = 8080;
|
|
||||||
private string _hostname;
|
|
||||||
private Grpc.Core.Server _server;
|
|
||||||
private ILibraryService _libraryService;
|
|
||||||
private ISettingsService _settingsService;
|
|
||||||
private IEventManager _eventManager;
|
|
||||||
|
|
||||||
//Implementation class declarations
|
|
||||||
private RemotePartyController _remotePartyController;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor. Registers GRPC service implementations.
|
|
||||||
/// </summary>
|
|
||||||
public ServerService(ILibraryService libraryService, ISettingsService settingsService, IEventManager eventManager)
|
|
||||||
{
|
|
||||||
string host = GetLocalIPAddress();
|
|
||||||
this._libraryService = libraryService;
|
|
||||||
this._settingsService = settingsService;
|
|
||||||
this._eventManager = eventManager;
|
|
||||||
if (string.IsNullOrWhiteSpace(host))
|
|
||||||
{
|
|
||||||
throw new Exception("This device must have a valid IP address");
|
|
||||||
}
|
|
||||||
|
|
||||||
_hostname = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Port
|
|
||||||
{
|
|
||||||
get { return _port; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Hostname
|
|
||||||
{
|
|
||||||
get { return _hostname; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Initialized
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (_remotePartyController != null &&
|
|
||||||
_server != null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start Server
|
|
||||||
/// </summary>
|
|
||||||
public void Start(string partyName, string description)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
Console.WriteLine(string.Format("Starting gRPC server at hostname: {0}, port: {1}", _hostname, _port));
|
|
||||||
|
|
||||||
_server = new Grpc.Core.Server
|
|
||||||
{
|
|
||||||
Ports = { new ServerPort(_hostname, _port, ServerCredentials.Insecure) }
|
|
||||||
};
|
|
||||||
|
|
||||||
//Construct implementations
|
|
||||||
_remotePartyController = new RemotePartyController(
|
|
||||||
partyName,
|
|
||||||
description,
|
|
||||||
_libraryService,
|
|
||||||
_settingsService,
|
|
||||||
_eventManager);
|
|
||||||
|
|
||||||
// Register grpc RemoteService with singleton server service
|
|
||||||
RegisterService(RemotePartyService.BindService(_remotePartyController));
|
|
||||||
|
|
||||||
|
|
||||||
_server.Start();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(string.Format("Error starting gRPC server: {0}", ex.Message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shutdown server async.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task</returns>
|
|
||||||
public async Task Stop()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _server.ShutdownAsync();
|
|
||||||
await _server.ShutdownTask;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(string.Format("Error stopping gRPC server: {0}", ex.Message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Reset()
|
|
||||||
{
|
|
||||||
await Stop();
|
|
||||||
_server = new Grpc.Core.Server
|
|
||||||
{
|
|
||||||
Ports = { new ServerPort("localhost", _port, ServerCredentials.Insecure) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterService(ServerServiceDefinition definition)
|
|
||||||
{
|
|
||||||
_server.Services.Add(definition);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetLocalIPAddress()
|
|
||||||
{
|
|
||||||
string returnIp = "";
|
|
||||||
var host = Dns.GetHostEntry(Dns.GetHostName());
|
|
||||||
foreach (var ip in host.AddressList)
|
|
||||||
{
|
|
||||||
if (ip.AddressFamily == AddressFamily.InterNetwork)
|
|
||||||
{
|
|
||||||
returnIp = ip.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnIp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,7 @@
|
|||||||
<ContentView
|
<ContentView
|
||||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
xmlns:dg="clr-namespace:Aurora.Design.Components.DataGrid"
|
xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid"
|
||||||
x:Class="Aurora.Design.Components.Library.Library">
|
x:Class="Aurora.Design.Components.Library.Library">
|
||||||
<ContentView.Resources>
|
<ContentView.Resources>
|
||||||
<StyleSheet
|
<StyleSheet
|
@ -12,7 +12,6 @@ namespace Aurora.Design.Components.NavigationMenu
|
|||||||
public NavigationItem()
|
public NavigationItem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public int Id { get; set; }
|
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Group { get; set; }
|
public string Group { get; set; }
|
||||||
public Type TargetType { get; set; }
|
public Type TargetType { get; set; }
|
@ -0,0 +1,50 @@
|
|||||||
|
using Aurora.Models.Media;
|
||||||
|
using Aurora.Design.Views.Main;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Views
|
||||||
|
{
|
||||||
|
public class BasePlayerViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
public BasePlayerViewModel(): base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate for interacting with main screen player control
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public SetPlayerDelegate ChangePlayerState { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate for checking if main screen player control is currently playing
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public GetIsPlayingDelegate IsPlaying { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command event handler for player play button
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnPlayButtonCommandExecute() { }
|
||||||
|
public virtual bool CanPlayButtonCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command event handler for player next button
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnNextButtonExecute() { }
|
||||||
|
public virtual bool CanNextButtonCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command event handler for player previous button
|
||||||
|
/// </summary>
|
||||||
|
public virtual void OnPreviousButtonExecute() { }
|
||||||
|
public virtual bool CanPreviousButtonCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,55 +15,14 @@ namespace Aurora.Design.Views
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Player
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command event handler for player play button
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnPlayButtonCommandExecute() { }
|
|
||||||
public virtual bool CanPlayButtonCommandExecute()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command event handler for player next button
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnNextButtonExecute() { }
|
|
||||||
public virtual bool CanNextButtonCommandExecute()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command event handler for player previous button
|
|
||||||
/// </summary>
|
|
||||||
public virtual void OnPreviousButtonExecute() { }
|
|
||||||
public virtual bool CanPreviousButtonCommandExecute()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delegate for interacting with main screen player control
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public SetPlayerDelegate ChangePlayerState { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delegate for checking if main screen player control is currently playing
|
|
||||||
/// </summary>
|
|
||||||
/// <value></value>
|
|
||||||
public GetIsPlayingDelegate IsPlaying { get; set; }
|
|
||||||
|
|
||||||
public ShowModalDelegate ShowModal { get; set; }
|
public ShowModalDelegate ShowModal { get; set; }
|
||||||
|
|
||||||
public HideModalDelegate HideModal { get; set; }
|
public HideModalDelegate HideModal { get; set; }
|
||||||
|
|
||||||
|
public SetViewDelegate SetView { get; set; }
|
||||||
|
|
||||||
#endregion Player
|
|
||||||
|
|
||||||
#region Lifecycle
|
#region Lifecycle Callbacks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called by main screen on view appearing
|
/// Called by main screen on view appearing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -78,7 +37,7 @@ namespace Aurora.Design.Views
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual Task OnInactive() { return Task.FromResult<object>(null); }
|
public virtual Task OnInactive() { return Task.FromResult<object>(null); }
|
||||||
|
|
||||||
#endregion
|
#endregion Lifecycle Callbacks
|
||||||
|
|
||||||
#region INotifyPropertyChanged Implementation
|
#region INotifyPropertyChanged Implementation
|
||||||
public bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
public bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
@ -31,11 +31,12 @@ namespace Aurora.Design.Views.Main
|
|||||||
public delegate void ShowModalDelegate(Type view, BaseDialogViewModel viewModel);
|
public delegate void ShowModalDelegate(Type view, BaseDialogViewModel viewModel);
|
||||||
public delegate void HideModalDelegate();
|
public delegate void HideModalDelegate();
|
||||||
public delegate void FinishDialogDelegate();
|
public delegate void FinishDialogDelegate();
|
||||||
|
public delegate void SetViewDelegate(Type viewType, Type viewModelType);
|
||||||
|
|
||||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||||
public partial class MainView : ContentPage//, IDisposable
|
public partial class MainView : ContentPage//, IDisposable
|
||||||
{
|
{
|
||||||
private Dictionary<int, BaseViewModel> _viewModels;
|
private Dictionary<string, BaseViewModel> _viewModels;
|
||||||
private BaseViewModel _lastViewModel;
|
private BaseViewModel _lastViewModel;
|
||||||
private Player _playerComponent;
|
private Player _playerComponent;
|
||||||
private IPlayer _playerService;
|
private IPlayer _playerService;
|
||||||
@ -45,7 +46,7 @@ namespace Aurora.Design.Views.Main
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
BindingContext = new MainViewModel();
|
BindingContext = new MainViewModel();
|
||||||
_viewModels = new Dictionary<int, BaseViewModel>();
|
_viewModels = new Dictionary<string, BaseViewModel>();
|
||||||
|
|
||||||
_playerComponent = Player;
|
_playerComponent = Player;
|
||||||
|
|
||||||
@ -74,29 +75,35 @@ namespace Aurora.Design.Views.Main
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var view = (View)Activator.CreateInstance(item.TargetType);
|
var view = (View)Activator.CreateInstance(item.TargetType);
|
||||||
|
string viewModelName = item.TargetViewModelType.Name;
|
||||||
|
|
||||||
//Check if we have an instantiated viewModel
|
//Check if we have an instantiated viewModel
|
||||||
BaseViewModel vm = new BaseViewModel();
|
BaseViewModel vm = new BaseViewModel();
|
||||||
if (_viewModels.ContainsKey(item.Id))
|
if (_viewModels.ContainsKey(viewModelName))
|
||||||
{
|
{
|
||||||
_viewModels.TryGetValue(item.Id, out vm);
|
_viewModels.TryGetValue(viewModelName, out vm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (item.TargetViewModelType.BaseType != typeof(BaseViewModel))
|
if (item.TargetViewModelType.IsAssignableFrom(typeof(BaseViewModel)))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel");
|
throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Instantiate new view model
|
//Instantiate new view model
|
||||||
vm = (BaseViewModel)App.Container.Resolve(item.TargetViewModelType); //Activator.CreateInstance(item.TargetViewModelType);
|
vm = (BaseViewModel)App.Container.Resolve(item.TargetViewModelType); //Activator.CreateInstance(item.TargetViewModelType);
|
||||||
_viewModels.Add(item.Id, vm);
|
_viewModels.Add(viewModelName, vm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Assign player controls to viewmodel
|
//Assign player controls to viewmodel
|
||||||
AssignPlayerControls(vm);
|
if(vm is BasePlayerViewModel)
|
||||||
|
{
|
||||||
|
AssignPlayerControls(vm as BasePlayerViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
ChangeModalVisiblity(false);
|
ChangeModalVisiblity(false);
|
||||||
|
vm.SetView = this.SetView;
|
||||||
|
|
||||||
//Activate viewmodel
|
//Activate viewmodel
|
||||||
vm.OnActive();
|
vm.OnActive();
|
||||||
@ -104,7 +111,10 @@ namespace Aurora.Design.Views.Main
|
|||||||
//Deactivate last viewModel
|
//Deactivate last viewModel
|
||||||
_lastViewModel.OnInactive();
|
_lastViewModel.OnInactive();
|
||||||
//Unasign deactivating vm
|
//Unasign deactivating vm
|
||||||
UnassignPlayerControls(_lastViewModel);
|
if(_lastViewModel is BasePlayerViewModel)
|
||||||
|
{
|
||||||
|
UnassignPlayerControls(_lastViewModel as BasePlayerViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
//Assign viewModel
|
//Assign viewModel
|
||||||
_lastViewModel = vm;
|
_lastViewModel = vm;
|
||||||
@ -128,20 +138,26 @@ namespace Aurora.Design.Views.Main
|
|||||||
var view = (View)Activator.CreateInstance(firstNavItem.TargetType);
|
var view = (View)Activator.CreateInstance(firstNavItem.TargetType);
|
||||||
|
|
||||||
BaseViewModel vm = new BaseViewModel();
|
BaseViewModel vm = new BaseViewModel();
|
||||||
if (_viewModels.ContainsKey(firstNavItem.Id))
|
if (_viewModels.ContainsKey(nameof(firstNavItem.TargetViewModelType)))
|
||||||
{
|
{
|
||||||
_viewModels.TryGetValue(firstNavItem.Id, out vm);
|
_viewModels.TryGetValue(nameof(firstNavItem.TargetViewModelType), out vm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Instantiate new view model
|
//Instantiate new view model
|
||||||
vm = (BaseViewModel)App.Container.Resolve(firstNavItem.TargetViewModelType); //(BaseViewModel)Activator.CreateInstance(firstNavItem.TargetViewModelType);
|
vm = (BaseViewModel)App.Container.Resolve(firstNavItem.TargetViewModelType); //(BaseViewModel)Activator.CreateInstance(firstNavItem.TargetViewModelType);
|
||||||
_viewModels.Add(firstNavItem.Id, vm);
|
_viewModels.Add(nameof(firstNavItem.TargetViewModelType), vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
view.BindingContext = vm;
|
view.BindingContext = vm;
|
||||||
_lastViewModel = vm;
|
_lastViewModel = vm;
|
||||||
AssignPlayerControls(vm);
|
if(vm is BasePlayerViewModel)
|
||||||
|
{
|
||||||
|
AssignPlayerControls(vm as BasePlayerViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.SetView = this.SetView;
|
||||||
|
|
||||||
ChangeModalVisiblity(false);
|
ChangeModalVisiblity(false);
|
||||||
vm.OnActive();
|
vm.OnActive();
|
||||||
|
|
||||||
@ -153,7 +169,7 @@ namespace Aurora.Design.Views.Main
|
|||||||
/// Unassign setplayer delegate to prevent vms from changing player info when inactive
|
/// Unassign setplayer delegate to prevent vms from changing player info when inactive
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vm"></param>
|
/// <param name="vm"></param>
|
||||||
private void UnassignPlayerControls(BaseViewModel vm)
|
private void UnassignPlayerControls(BasePlayerViewModel vm)
|
||||||
{
|
{
|
||||||
vm.ChangePlayerState = null;
|
vm.ChangePlayerState = null;
|
||||||
vm.IsPlaying = null;
|
vm.IsPlaying = null;
|
||||||
@ -164,7 +180,7 @@ namespace Aurora.Design.Views.Main
|
|||||||
/// Assign main views music player controls to a view model
|
/// Assign main views music player controls to a view model
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vm">BaseViewModel to assign controls to</param>
|
/// <param name="vm">BaseViewModel to assign controls to</param>
|
||||||
private void AssignPlayerControls(BaseViewModel vm)
|
private void AssignPlayerControls(BasePlayerViewModel vm)
|
||||||
{
|
{
|
||||||
_playerComponent.PlayButtonCommand = new Command(vm.OnPlayButtonCommandExecute, vm.CanPlayButtonCommandExecute);
|
_playerComponent.PlayButtonCommand = new Command(vm.OnPlayButtonCommandExecute, vm.CanPlayButtonCommandExecute);
|
||||||
_playerComponent.NextButtonCommand = new Command(vm.OnNextButtonExecute, vm.CanNextButtonCommandExecute);
|
_playerComponent.NextButtonCommand = new Command(vm.OnNextButtonExecute, vm.CanNextButtonCommandExecute);
|
||||||
@ -259,5 +275,53 @@ namespace Aurora.Design.Views.Main
|
|||||||
Modal.IsVisible = isVisible;
|
Modal.IsVisible = isVisible;
|
||||||
Content.IsVisible = !isVisible;
|
Content.IsVisible = !isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetView(Type viewType, Type viewModelType)
|
||||||
|
{
|
||||||
|
BaseViewModel vm = new BaseViewModel();
|
||||||
|
if(this._viewModels.ContainsKey(viewModelType.Name))
|
||||||
|
{
|
||||||
|
this._viewModels.TryGetValue(viewModelType.Name, out vm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (viewModelType.IsAssignableFrom(typeof(BaseViewModel)))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Instantiate new view model
|
||||||
|
vm = (BaseViewModel)App.Container.Resolve(viewModelType); //Activator.CreateInstance(item.TargetViewModelType);
|
||||||
|
_viewModels.Add(viewModelType.Name, vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Assign player controls to viewmodel
|
||||||
|
if(vm is BasePlayerViewModel)
|
||||||
|
{
|
||||||
|
AssignPlayerControls(vm as BasePlayerViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeModalVisiblity(false);
|
||||||
|
|
||||||
|
//Activate viewmodel
|
||||||
|
vm.OnActive();
|
||||||
|
|
||||||
|
//Deactivate last viewModel
|
||||||
|
_lastViewModel.OnInactive();
|
||||||
|
//Unasign deactivating vm
|
||||||
|
if(_lastViewModel is BasePlayerViewModel)
|
||||||
|
{
|
||||||
|
UnassignPlayerControls(_lastViewModel as BasePlayerViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
var view = (View)Activator.CreateInstance(viewType);
|
||||||
|
vm.SetView = this.SetView;
|
||||||
|
|
||||||
|
//Assign viewModel
|
||||||
|
_lastViewModel = vm;
|
||||||
|
view.BindingContext = vm;
|
||||||
|
|
||||||
|
_viewContent.Content = view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -56,13 +56,13 @@ namespace Aurora.Design.Views.MainView
|
|||||||
{
|
{
|
||||||
_pages = new ObservableCollection<NavigationItem>(new[]
|
_pages = new ObservableCollection<NavigationItem>(new[]
|
||||||
{
|
{
|
||||||
new NavigationItem { Id = 0, Title = "Songs", Group="Your Music", TargetType = typeof(SongsView), TargetViewModelType = typeof(SongsViewModel) },
|
new NavigationItem { Title = "Songs", Group="Your Music", TargetType = typeof(SongsView), TargetViewModelType = typeof(SongsViewModel) },
|
||||||
new NavigationItem { Id = 1, Title = "Artists", Group="Your Music", TargetType = typeof(ArtistsView), TargetViewModelType = typeof(ArtistsViewModel)},
|
new NavigationItem { Title = "Artists", Group="Your Music", TargetType = typeof(ArtistsView), TargetViewModelType = typeof(ArtistsViewModel)},
|
||||||
new NavigationItem { Id = 2, Title = "Albums", Group="Your Music", TargetType = typeof(AlbumsView), TargetViewModelType = typeof(AlbumsViewModel)},
|
new NavigationItem { Title = "Albums", Group="Your Music", TargetType = typeof(AlbumsView), TargetViewModelType = typeof(AlbumsViewModel)},
|
||||||
new NavigationItem { Id = 3, Title = "Stations", Group="Your Music", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)},
|
new NavigationItem { Title = "Stations", Group="Your Music", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)},
|
||||||
new NavigationItem { Id = 4, Title = "Party", Group="Social", TargetType = typeof(PartyView), TargetViewModelType = typeof(PartyViewModel)},
|
new NavigationItem { Title = "Party", Group="Social", TargetType = typeof(PartyView), TargetViewModelType = typeof(PartyViewModel)},
|
||||||
new NavigationItem { Id = 5, Title = "Profile", Group="Social", TargetType = typeof(ProfileView), TargetViewModelType = typeof(ProfileViewModel)},
|
new NavigationItem { Title = "Profile", Group="Social", TargetType = typeof(ProfileView), TargetViewModelType = typeof(ProfileViewModel)},
|
||||||
new NavigationItem { Id = 6, Title = "A + B", Group="Playlists", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)}
|
new NavigationItem { Title = "A + B", Group="Playlists", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Aurora.Proto.Party;
|
||||||
|
using Aurora.Models.Media;
|
||||||
|
using Aurora.Services.Settings;
|
||||||
|
using Aurora.Services;
|
||||||
|
|
||||||
|
namespace Aurora.Design.Views.Party
|
||||||
|
{
|
||||||
|
public class BasePartyViewModel : BasePlayerViewModel
|
||||||
|
{
|
||||||
|
protected string _hostname;
|
||||||
|
protected Global _global;
|
||||||
|
|
||||||
|
protected ISettingsService _settingsService;
|
||||||
|
private ObservableCollection<Member> _members;
|
||||||
|
private ObservableCollection<BaseMedia> _queue;
|
||||||
|
private BaseMedia _selectedMedia;
|
||||||
|
|
||||||
|
private int _selectedTabIndex;
|
||||||
|
|
||||||
|
public BasePartyViewModel(
|
||||||
|
ISettingsService settingsService,
|
||||||
|
Global global
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_members = new ObservableCollection<Member>();
|
||||||
|
_queue = new ObservableCollection<BaseMedia>();
|
||||||
|
|
||||||
|
this._settingsService = settingsService;
|
||||||
|
this._global = global;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SelectedTabIndex
|
||||||
|
{
|
||||||
|
get { return _selectedTabIndex; }
|
||||||
|
set { SetProperty(ref _selectedTabIndex, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Publc property for the members list
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public ObservableCollection<Member> Members
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _members;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetProperty(ref _members, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public property for the currently selected song.
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public BaseMedia SelectedMedia
|
||||||
|
{
|
||||||
|
get { return _selectedMedia; }
|
||||||
|
set { SetProperty(ref _selectedMedia, value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,225 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using Grpc.Core;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Aurora.Services.EventManager;
|
||||||
|
using Aurora.Services.Library;
|
||||||
|
using Aurora.Services.Settings;
|
||||||
|
using Aurora.Services;
|
||||||
|
using Aurora.Proto.Party;
|
||||||
|
using Aurora.Models.Media;
|
||||||
|
using Aurora.Services.Controllers;
|
||||||
|
using Aurora.Utils;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Aurora.Design.Views.Party
|
||||||
|
{
|
||||||
|
public class HostPartyViewModel : BasePartyViewModel
|
||||||
|
{
|
||||||
|
private IEventManager _eventManager;
|
||||||
|
private ILibraryService _libraryService;
|
||||||
|
|
||||||
|
private Grpc.Core.Server _server;
|
||||||
|
private RemotePartyController _remotePartyController;
|
||||||
|
private Channel _channel;
|
||||||
|
private int _port = 8080;
|
||||||
|
private bool _isServerStarted = false;
|
||||||
|
|
||||||
|
public HostPartyViewModel(
|
||||||
|
ISettingsService settingsService,
|
||||||
|
IEventManager eventManager,
|
||||||
|
ILibraryService libraryService,
|
||||||
|
Global global
|
||||||
|
): base(settingsService, global)
|
||||||
|
{
|
||||||
|
this._eventManager = eventManager;
|
||||||
|
this._global.State = PartyState.Hosting;
|
||||||
|
this._libraryService = libraryService;
|
||||||
|
|
||||||
|
// Create and start grpc server
|
||||||
|
string host = IpUtil.GetLocalIPAddress();
|
||||||
|
if(string.IsNullOrWhiteSpace(host))
|
||||||
|
{
|
||||||
|
// TODO display error to screen
|
||||||
|
throw new System.Exception("This device does not have a valid IP address");
|
||||||
|
}
|
||||||
|
this._hostname = IpUtil.GetLocalIPAddress();
|
||||||
|
|
||||||
|
this.StartServer("test", "test description");
|
||||||
|
|
||||||
|
// TODO assign members
|
||||||
|
// TODO assign songList
|
||||||
|
|
||||||
|
// Register commands
|
||||||
|
PlayCommand = new Command(OnDoubleClickCommandExecute, CanDoubleClickCommandExecute);
|
||||||
|
LeavePartyCommand = new Command(OnLeavePartyCommandExecute, CanLeavePartyCommandExecute);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public property for playing media command
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public Command PlayCommand { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Public property for leave party command
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public Command LeavePartyCommand { get; private set; }
|
||||||
|
|
||||||
|
#endregion Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called by framework when view becomes active
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Task OnActive()
|
||||||
|
{
|
||||||
|
// Start server if not already started
|
||||||
|
if(!this._isServerStarted)
|
||||||
|
{
|
||||||
|
this._hostname = IpUtil.GetLocalIPAddress();
|
||||||
|
|
||||||
|
this.StartServer("test", "test description");
|
||||||
|
}
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called by framework when view becomes inactive
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Task OnInactive()
|
||||||
|
{
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnLeavePartyCommandExecute()
|
||||||
|
{
|
||||||
|
await this._channel.ShutdownAsync();
|
||||||
|
await this._server.ShutdownAsync();
|
||||||
|
this._global.State = PartyState.Idle;
|
||||||
|
this.SetView(typeof(PartyView), typeof(PartyViewModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanLeavePartyCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnPlayButtonCommandExecute()
|
||||||
|
{
|
||||||
|
if (base.IsPlaying())
|
||||||
|
{
|
||||||
|
//Fire play stopped event
|
||||||
|
AudioMetadata meta = SelectedMedia.Metadata as AudioMetadata;
|
||||||
|
MediaPausedEvent mediaPaused = new MediaPausedEvent();
|
||||||
|
|
||||||
|
_eventManager.FireEvent(new BaseEvent()
|
||||||
|
{
|
||||||
|
MediaPausedEvent = mediaPaused
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Fire play resume event
|
||||||
|
AudioMetadata meta = SelectedMedia.Metadata as AudioMetadata;
|
||||||
|
MediaResumedEvent mediaResumed = new MediaResumedEvent();
|
||||||
|
|
||||||
|
_eventManager.FireEvent(new BaseEvent()
|
||||||
|
{
|
||||||
|
MediaResumedEvent = mediaResumed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanPlayButtonCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanNextButtonCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanPreviousButtonCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// On double click execute, fire media playing event
|
||||||
|
/// </summary>
|
||||||
|
public void OnDoubleClickCommandExecute()
|
||||||
|
{
|
||||||
|
//Fire Playing event
|
||||||
|
AudioMetadata meta = SelectedMedia.Metadata as AudioMetadata;
|
||||||
|
NewMediaPlayingEvent mediaPlaying = new NewMediaPlayingEvent()
|
||||||
|
{
|
||||||
|
Media = new Media()
|
||||||
|
{
|
||||||
|
//TODO need full resource name
|
||||||
|
Name = SelectedMedia.Id,
|
||||||
|
Title = meta.Title,
|
||||||
|
Artist = meta.Artist,
|
||||||
|
Album = meta.Album,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_eventManager.FireEvent(new BaseEvent()
|
||||||
|
{
|
||||||
|
NewMediaPlayingEvent = mediaPlaying
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanDoubleClickCommandExecute()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private void StartServer(string partyName, string description)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO bmw replace with display in UI
|
||||||
|
Console.WriteLine(string.Format("Starting gRPC server at hostname: {0}, port: {1}", _hostname, _port));
|
||||||
|
|
||||||
|
_server = new Grpc.Core.Server
|
||||||
|
{
|
||||||
|
Ports = { new ServerPort(_hostname, _port, ServerCredentials.Insecure) }
|
||||||
|
};
|
||||||
|
|
||||||
|
//Construct implementations
|
||||||
|
this._remotePartyController = new RemotePartyController(
|
||||||
|
partyName,
|
||||||
|
description,
|
||||||
|
this._libraryService,
|
||||||
|
base._settingsService,
|
||||||
|
_eventManager);
|
||||||
|
|
||||||
|
// Register grpc RemoteService with singleton server service
|
||||||
|
RemotePartyService.BindService(this._remotePartyController);
|
||||||
|
|
||||||
|
|
||||||
|
_server.Start();
|
||||||
|
this._isServerStarted = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// TODO bmw replace with display in UI
|
||||||
|
Console.WriteLine(string.Format("Error starting gRPC server: {0}", ex.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion Private Methods
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user