Merge pull request #349 from peppy/installer-updater

Automatic updates.
This commit is contained in:
Thomas Müller 2017-02-12 12:16:03 +01:00 committed by GitHub
commit ff6838f88c
15 changed files with 395 additions and 126 deletions

@ -1 +1 @@
Subproject commit 16cc4a53a0447264b8f67f149da701c4f00a41ea Subproject commit e776f6f2729bbe93206c4e8c089eeca57522fcf7

View File

@ -88,13 +88,13 @@ namespace osu.Desktop.VisualTests.Tests
if (n.Progress < 1) if (n.Progress < 1)
n.Progress += (float)(Time.Elapsed / 2000) * RNG.NextSingle(); n.Progress += (float)(Time.Elapsed / 2000) * RNG.NextSingle();
else else
n.Complete(); n.State = ProgressNotificationState.Completed;
} }
} }
private void sendProgress2() private void sendProgress2()
{ {
var n = new ProgressNotification(@"Downloading Haitai..."); var n = new ProgressNotification { Text = @"Downloading Haitai..." };
manager.Post(n); manager.Post(n);
progressingNotifications.Add(n); progressingNotifications.Add(n);
} }
@ -103,19 +103,19 @@ namespace osu.Desktop.VisualTests.Tests
private void sendProgress1() private void sendProgress1()
{ {
var n = new ProgressNotification(@"Uploading to BSS..."); var n = new ProgressNotification { Text = @"Uploading to BSS..." };
manager.Post(n); manager.Post(n);
progressingNotifications.Add(n); progressingNotifications.Add(n);
} }
private void sendNotification2() private void sendNotification2()
{ {
manager.Post(new SimpleNotification(@"You are amazing")); manager.Post(new SimpleNotification { Text = @"You are amazing" });
} }
private void sendNotification1() private void sendNotification1()
{ {
manager.Post(new SimpleNotification(@"Welcome to osu!. Enjoy your stay!")); manager.Post(new SimpleNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
} }
} }
} }

View File

@ -11,6 +11,9 @@ using System.Windows.Forms;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Desktop.Platform; using osu.Framework.Desktop.Platform;
using osu.Game.Database; using osu.Game.Database;
using osu.Desktop.Overlays;
using System.Reflection;
using System.Drawing;
namespace osu.Desktop namespace osu.Desktop
{ {
@ -22,12 +25,22 @@ namespace osu.Desktop
} }
protected override void LoadComplete()
{
base.LoadComplete();
(new VersionManager()).Preload(this, Add);
}
public override void SetHost(BasicGameHost host) public override void SetHost(BasicGameHost host)
{ {
base.SetHost(host); base.SetHost(host);
var desktopWindow = host.Window as DesktopGameWindow; var desktopWindow = host.Window as DesktopGameWindow;
if (desktopWindow != null) if (desktopWindow != null)
{ {
desktopWindow.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
desktopWindow.Title = @"osu!lazer";
desktopWindow.DragEnter += dragEnter; desktopWindow.DragEnter += dragEnter;
desktopWindow.DragDrop += dragDrop; desktopWindow.DragDrop += dragDrop;
} }

View File

@ -0,0 +1,93 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using Squirrel;
using System.Reflection;
namespace osu.Desktop.Overlays
{
public class VersionManager : OverlayContainer
{
private UpdateManager updateManager;
private NotificationManager notification;
[BackgroundDependencyLoader]
private void load(NotificationManager notification)
{
this.notification = notification;
AutoSizeAxes = Axes.Both;
Anchor = Anchor.BottomCentre;
Origin = Anchor.BottomCentre;
var asm = Assembly.GetEntryAssembly().GetName();
Add(new OsuSpriteText
{
Text = $@"osu!lazer v{asm.Version}"
});
updateChecker();
}
protected override void LoadComplete()
{
base.LoadComplete();
State = Visibility.Visible;
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
updateManager?.Dispose();
}
private async void updateChecker()
{
updateManager = await UpdateManager.GitHubUpdateManager(@"https://github.com/ppy/osu", @"osulazer", null, null, true);
var info = await updateManager.CheckForUpdate();
if (info.ReleasesToApply.Count > 0)
{
ProgressNotification n = new UpdateProgressNotification
{
Text = @"Downloading update..."
};
Schedule(() => notification.Post(n));
Schedule(() => n.State = ProgressNotificationState.Active);
await updateManager.DownloadReleases(info.ReleasesToApply, (int p) => Schedule(() => n.Progress = p / 100f));
Schedule(() => n.Text = @"Installing update...");
await updateManager.ApplyReleases(info, (int p) => Schedule(() => n.Progress = p / 100f));
Schedule(() => n.State = ProgressNotificationState.Completed);
}
else
{
//check again every 30 minutes.
Scheduler.AddDelayed(updateChecker, 60000 * 30);
}
}
protected override void PopIn()
{
}
protected override void PopOut()
{
}
class UpdateProgressNotification : ProgressNotification
{
protected override Notification CreateCompletionNotification() => new ProgressCompletionNotification(this)
{
Text = @"Update ready to install. Click to restart!",
Activated = () =>
{
UpdateManager.RestartApp();
return true;
}
};
}
}
}

View File

@ -0,0 +1,26 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu!lazer")]
[assembly: AssemblyDescription("click the circles. to the beat.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ppy Pty Ltd")]
[assembly: AssemblyProduct("osu!lazer")]
[assembly: AssemblyCopyright("ppy Pty Ltd 2007-2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("55e28cb2-7b6c-4595-8dcc-9871d8aad7e9")]
[assembly: AssemblyVersion("0.0.3")]
[assembly: AssemblyFileVersion("0.0.3")]

11
osu.Desktop/app.config Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -79,19 +79,73 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Win32Resource>osu!.res</Win32Resource> <Win32Resource>
</Win32Resource>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>lazer.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="DeltaCompressionDotNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DeltaCompressionDotNet.MsDelta, Version=1.0.0.0, Culture=neutral, PublicKeyToken=46b2138a390abf55, processorArchitecture=MSIL">
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.MsDelta.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="DeltaCompressionDotNet.PatchApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3e8888ee913ed789, processorArchitecture=MSIL">
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.PatchApi.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="mscorlib" /> <Reference Include="mscorlib" />
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" /> <Reference Include="OpenTK, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4" />
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Squirrel, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\osu.licenseheader"> <None Include="..\osu.licenseheader">
<Link>osu.licenseheader</Link> <Link>osu.licenseheader</Link>
</None> </None>
<None Include="app.config" />
<None Include="osu!.res" /> <None Include="osu!.res" />
<None Include="packages.config" />
<None Include="Properties\app.manifest" /> <None Include="Properties\app.manifest" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -157,10 +211,14 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="OsuGameDesktop.cs" /> <Compile Include="OsuGameDesktop.cs" />
<Compile Include="Overlays\VersionManager.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" /> <Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="lazer.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DeltaCompressionDotNet" version="1.0.0" targetFramework="net45" />
<package id="Mono.Cecil" version="0.9.6.1" targetFramework="net45" />
<package id="Splat" version="1.6.2" targetFramework="net45" />
<package id="squirrel.windows" version="1.5.2" targetFramework="net45" />
</packages>

View File

@ -83,11 +83,14 @@ namespace osu.Game.Database
connection.DeleteAll<BeatmapInfo>(); connection.DeleteAll<BeatmapInfo>();
} }
public void Import(params string[] paths) public void Import(IEnumerable<string> paths)
{ {
foreach (string p in paths) foreach (string p in paths)
Import(p);
}
public void Import(string path)
{ {
var path = p;
string hash = null; string hash = null;
BeatmapMetadata metadata; BeatmapMetadata metadata;
@ -141,7 +144,6 @@ namespace osu.Game.Database
Import(new[] { beatmapSet }); Import(new[] { beatmapSet });
} }
}
public void Import(IEnumerable<BeatmapSetInfo> beatmapSets) public void Import(IEnumerable<BeatmapSetInfo> beatmapSets)
{ {

View File

@ -24,6 +24,7 @@ using osu.Game.Screens.Menu;
using OpenTK; using OpenTK;
using System.Linq; using System.Linq;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using System.Collections.Generic;
namespace osu.Game namespace osu.Game
{ {
@ -67,14 +68,17 @@ namespace osu.Game
} }
if (args?.Length > 0) if (args?.Length > 0)
ImportBeatmaps(args); {
var paths = args.Where(a => !a.StartsWith(@"-"));
ImportBeatmaps(paths);
}
Dependencies.Cache(this); Dependencies.Cache(this);
PlayMode = LocalConfig.GetBindable<PlayMode>(OsuConfig.PlayMode); PlayMode = LocalConfig.GetBindable<PlayMode>(OsuConfig.PlayMode);
} }
public void ImportBeatmaps(params string[] paths) public void ImportBeatmaps(IEnumerable<string> paths)
{ {
Schedule(delegate { Dependencies.Get<BeatmapDatabase>().Import(paths); }); Schedule(delegate { Dependencies.Get<BeatmapDatabase>().Import(paths); });
} }

View File

@ -73,6 +73,8 @@ namespace osu.Game.Overlays
public void Post(Notification notification) public void Post(Notification notification)
{ {
State = Visibility.Visible;
++runningDepth; ++runningDepth;
notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth;

View File

@ -53,8 +53,7 @@ namespace osu.Game.Overlays.Notifications
} }
} }
[BackgroundDependencyLoader] public Notification()
private void load(OsuColour colours)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;

View File

@ -1,6 +1,8 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics;
namespace osu.Game.Overlays.Notifications namespace osu.Game.Overlays.Notifications
{ {
public class ProgressCompletionNotification : SimpleNotification public class ProgressCompletionNotification : SimpleNotification
@ -8,9 +10,9 @@ namespace osu.Game.Overlays.Notifications
private ProgressNotification progressNotification; private ProgressNotification progressNotification;
public ProgressCompletionNotification(ProgressNotification progressNotification) public ProgressCompletionNotification(ProgressNotification progressNotification)
: base(@"Task has completed!")
{ {
this.progressNotification = progressNotification; this.progressNotification = progressNotification;
Icon = FontAwesome.fa_check;
} }
} }
} }

View File

@ -16,26 +16,42 @@ namespace osu.Game.Overlays.Notifications
{ {
public class ProgressNotification : Notification, IHasCompletionTarget public class ProgressNotification : Notification, IHasCompletionTarget
{ {
private string text; public string Text
private float progress;
public float Progress
{ {
get { return progress; } get { return textDrawable.Text; }
set set
{ {
Debug.Assert(state == ProgressNotificationState.Active); textDrawable.Text = value;
progress = value;
progressBar.Progress = progress;
} }
} }
public ProgressNotificationState State public float Progress
{
get { return progressBar.Progress; }
set
{
progressBar.Progress = value;
}
}
protected override void LoadComplete()
{
base.LoadComplete();
//we may have received changes before we were displayed.
State = state;
}
public virtual ProgressNotificationState State
{ {
get { return state; } get { return state; }
set set
{ {
bool stateChanged = state != value;
state = value; state = value;
if (IsLoaded)
{
switch (state) switch (state)
{ {
case ProgressNotificationState.Queued: case ProgressNotificationState.Queued:
@ -55,11 +71,36 @@ namespace osu.Game.Overlays.Notifications
break; break;
} }
} }
if (stateChanged)
{
switch (state)
{
case ProgressNotificationState.Completed:
NotificationContent.MoveToY(-DrawSize.Y / 2, 200, EasingTypes.OutQuint);
FadeTo(0.01f, 200); //don't completely fade out or our scheduled task won't run.
Delay(100);
Schedule(Completed);
break;
}
}
}
} }
private ProgressNotificationState state; private ProgressNotificationState state;
public Action Completed; protected virtual Notification CreateCompletionNotification() => new ProgressCompletionNotification(this)
{
Activated = CompletionClickAction,
Text = $"Task \"{Text}\" has completed!"
};
protected virtual void Completed()
{
Expire();
CompletionTarget?.Invoke(CreateCompletionNotification());
}
public override bool DisplayOnTop => false; public override bool DisplayOnTop => false;
@ -68,30 +109,21 @@ namespace osu.Game.Overlays.Notifications
private Color4 colourActive; private Color4 colourActive;
private Color4 colourCancelled; private Color4 colourCancelled;
public ProgressNotification(string text) private SpriteText textDrawable;
{
this.text = text;
}
[BackgroundDependencyLoader] public ProgressNotification()
private void load(OsuColour colours)
{ {
colourQueued = colours.YellowDark;
colourActive = colours.Blue;
colourCancelled = colours.Red;
IconContent.Add(new Box IconContent.Add(new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}); });
Content.Add(new SpriteText Content.Add(textDrawable = new SpriteText
{ {
TextSize = 16, TextSize = 16,
Colour = OsuColour.Gray(128), Colour = OsuColour.Gray(128),
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Text = text
}); });
NotificationContent.Add(progressBar = new ProgressBar NotificationContent.Add(progressBar = new ProgressBar
@ -104,21 +136,12 @@ namespace osu.Game.Overlays.Notifications
State = ProgressNotificationState.Queued; State = ProgressNotificationState.Queued;
} }
public void Complete() [BackgroundDependencyLoader]
private void load(OsuColour colours)
{ {
Debug.Assert(state != ProgressNotificationState.Completed); colourQueued = colours.YellowDark;
colourActive = colours.Blue;
state = ProgressNotificationState.Completed; colourCancelled = colours.Red;
NotificationContent.MoveToY(-DrawSize.Y / 2, 200, EasingTypes.OutQuint);
FadeTo(0.01f, 200); //don't completely fade out or our scheduled task won't run.
Delay(100);
Schedule(() =>
{
CompletionTarget?.Invoke(new ProgressCompletionNotification(this));
base.Close();
});
} }
public override void Close() public override void Close()
@ -135,8 +158,16 @@ namespace osu.Game.Overlays.Notifications
} }
} }
/// <summary>
/// The function to post completion notifications back to.
/// </summary>
public Action<Notification> CompletionTarget { get; set; } public Action<Notification> CompletionTarget { get; set; }
/// <summary>
/// An action to complete when the completion notification is clicked.
/// </summary>
public Func<bool> CompletionClickAction;
class ProgressBar : Container class ProgressBar : Container
{ {
private Box box; private Box box;

View File

@ -12,14 +12,31 @@ namespace osu.Game.Overlays.Notifications
public class SimpleNotification : Notification public class SimpleNotification : Notification
{ {
private string text; private string text;
public string Text
public SimpleNotification(string text)
{ {
this.text = text; get { return text; }
set
{
text = value;
textDrawable.Text = text;
}
} }
[BackgroundDependencyLoader] private FontAwesome icon = FontAwesome.fa_info_circle;
private void load(OsuColour colours) public FontAwesome Icon
{
get { return icon; }
set
{
icon = value;
iconDrawable.Icon = icon;
}
}
private SpriteText textDrawable;
private TextAwesome iconDrawable;
public SimpleNotification()
{ {
IconContent.Add(new Drawable[] IconContent.Add(new Drawable[]
{ {
@ -28,14 +45,14 @@ namespace osu.Game.Overlays.Notifications
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
ColourInfo = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.5f)) ColourInfo = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.5f))
}, },
new TextAwesome iconDrawable = new TextAwesome
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Icon = FontAwesome.fa_info_circle, Icon = icon ,
} }
}); });
Content.Add(new SpriteText Content.Add(textDrawable = new SpriteText
{ {
TextSize = 16, TextSize = 16,
Colour = OsuColour.Gray(128), Colour = OsuColour.Gray(128),
@ -43,7 +60,11 @@ namespace osu.Game.Overlays.Notifications
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Text = text Text = text
}); });
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Light.Colour = colours.Green; Light.Colour = colours.Green;
} }