1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 21:52:55 +08:00

Group export methods into their respective managers

This commit is contained in:
cdwcgt 2022-12-11 18:30:24 +09:00
parent a87bcccc42
commit e02b8cb199
No known key found for this signature in database
GPG Key ID: 144396D01095C3A2
10 changed files with 80 additions and 87 deletions

View File

@ -42,6 +42,8 @@ namespace osu.Game.Beatmaps
private readonly WorkingBeatmapCache workingBeatmapCache;
private readonly LegacyBeatmapExporter beatmapExporter;
public Action<(BeatmapSetInfo beatmapSet, bool isBatch)>? ProcessBeatmap { private get; set; }
public BeatmapManager(Storage storage, RealmAccess realm, IAPIProvider? api, AudioManager audioManager, IResourceStore<byte[]> gameResources, GameHost? host = null,
@ -66,6 +68,11 @@ namespace osu.Game.Beatmaps
beatmapImporter.PostNotification = obj => PostNotification?.Invoke(obj);
workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host);
beatmapExporter = new LegacyBeatmapExporter(storage, realm)
{
PostNotification = obj => PostNotification?.Invoke(obj)
};
}
protected virtual WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore<byte[]> resources, IResourceStore<byte[]> storage, WorkingBeatmap? defaultBeatmap,
@ -446,6 +453,8 @@ namespace osu.Game.Beatmaps
public Task<Live<BeatmapSetInfo>?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original) =>
beatmapImporter.ImportAsUpdate(notification, importTask, original);
public void Export(BeatmapSetInfo beatmap) => Task.Run(() => beatmapExporter.ExportAsync(beatmap));
private void updateHashAndMarkDirty(BeatmapSetInfo setInfo)
{
setInfo.Hash = beatmapImporter.ComputeHash(setInfo);

View File

@ -3,14 +3,13 @@
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Overlays;
namespace osu.Game.Database
{
public class LegacyBeatmapExporter : LegacyModelExporter<BeatmapSetInfo>
{
public LegacyBeatmapExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null)
: base(storage, realm, notifications)
public LegacyBeatmapExporter(Storage storage, RealmAccess realm)
: base(storage, realm)
{
}

View File

@ -9,7 +9,6 @@ using System.Threading.Tasks;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Extensions;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Utils;
using Realms;
@ -33,26 +32,16 @@ namespace osu.Game.Database
protected RealmAccess RealmAccess;
private readonly ProgressNotification notification;
private bool canCancel = true;
private readonly INotificationOverlay? notifications;
private string filename = string.Empty;
public Action<Notification>? PostNotification { get; set; }
protected LegacyModelExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null)
protected LegacyModelExporter(Storage storage, RealmAccess realm)
{
exportStorage = storage.GetStorageForDirectory(@"exports");
UserFileStorage = storage.GetStorageForDirectory(@"files");
RealmAccess = realm;
this.notifications = notifications;
notification = new ProgressNotification
{
State = ProgressNotificationState.Active,
Text = "Exporting...",
CompletionText = "Export completed"
};
notification.CancelRequested += () => canCancel;
}
/// <summary>
@ -62,13 +51,9 @@ namespace osu.Game.Database
/// <returns></returns>
public async Task ExportAsync(TModel model)
{
notifications?.Post(notification);
string itemFilename = model.GetDisplayString().GetValidFilename();
IEnumerable<string> existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}");
string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}");
notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename);
filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}");
using (var stream = exportStorage.CreateFileSafely(filename))
{
@ -77,22 +62,50 @@ namespace osu.Game.Database
}
/// <summary>
/// Export te model corresponding to model to given stream.
/// Export model to stream.
/// </summary>
/// <param name="model">The medel which have <see cref="IHasGuidPrimaryKey"/>.</param>
/// <param name="stream">The stream to export.</param>
/// <returns></returns>
public async Task ExportToStreamAsync(TModel model, Stream stream)
{
ProgressNotification notification = new ProgressNotification
{
State = ProgressNotificationState.Active,
Text = "Exporting...",
CompletionText = "Export completed"
};
notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename);
notification.CancelRequested += () => canCancel;
PostNotification?.Invoke(notification);
canCancel = true;
Guid id = model.ID;
await Task.Run(() =>
{
RealmAccess.Run(r =>
{
TModel refetchModel = r.Find<TModel>(id);
ExportToStream(refetchModel, stream);
ExportToStream(refetchModel, stream, notification);
});
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
notification.State = ProgressNotificationState.Cancelled;
Logger.Error(t.Exception, "An error occurred while exporting");
return;
}
if (notification.CancellationToken.IsCancellationRequested)
{
return;
}
notification.CompletionText = "Export Complete, Click to open the folder";
notification.State = ProgressNotificationState.Completed;
});
}).ContinueWith(onComplete);
}
/// <summary>
@ -101,14 +114,16 @@ namespace osu.Game.Database
/// </summary>
/// <param name="model">The item to export.</param>
/// <param name="outputStream">The output stream to export to.</param>
protected virtual void ExportToStream(TModel model, Stream outputStream) => exportZipArchive(model, outputStream);
/// <param name="notification">The notification will displayed to the user</param>
protected virtual void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification) => exportZipArchive(model, outputStream, notification);
/// <summary>
/// Exports an item to Stream as a legacy (.zip based) package.
/// </summary>
/// <param name="model">The item to export.</param>
/// <param name="outputStream">The output stream to export to.</param>
private void exportZipArchive(TModel model, Stream outputStream)
/// <param name="notification">The notification will displayed to the user</param>
private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification)
{
using (var archive = ZipArchive.Create())
{
@ -129,24 +144,5 @@ namespace osu.Game.Database
archive.SaveTo(outputStream);
}
}
private void onComplete(Task t)
{
if (t.IsFaulted)
{
notification.State = ProgressNotificationState.Cancelled;
Logger.Error(t.Exception, "An error occurred while exporting");
return;
}
if (notification.CancellationToken.IsCancellationRequested)
{
return;
}
notification.CompletionText = "Export Complete, Click to open the folder";
notification.State = ProgressNotificationState.Completed;
}
}
}

View File

@ -5,21 +5,21 @@ using System.IO;
using System.Linq;
using osu.Framework.Platform;
using osu.Game.Extensions;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Scoring;
namespace osu.Game.Database
{
public class LegacyScoreExporter : LegacyModelExporter<ScoreInfo>
{
public LegacyScoreExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null)
: base(storage, realm, notifications)
public LegacyScoreExporter(Storage storage, RealmAccess realm)
: base(storage, realm)
{
}
protected override string FileExtension => ".osr";
protected override void ExportToStream(ScoreInfo model, Stream stream)
protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification notification)
{
var file = model.Files.SingleOrDefault();
if (file == null)

View File

@ -2,15 +2,14 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Platform;
using osu.Game.Overlays;
using osu.Game.Skinning;
namespace osu.Game.Database
{
public class LegacySkinExporter : LegacyModelExporter<SkinInfo>
{
public LegacySkinExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null)
: base(storage, realm, notifications)
public LegacySkinExporter(Storage storage, RealmAccess realm)
: base(storage, realm)
{
}

View File

@ -6,7 +6,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
@ -18,7 +17,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
@ -34,7 +32,6 @@ using osuTK.Graphics;
using osu.Game.Online.API;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Utils;
using osu.Framework.Platform;
namespace osu.Game.Online.Leaderboards
{
@ -73,18 +70,11 @@ namespace osu.Game.Online.Leaderboards
[Resolved(canBeNull: true)]
private SongSelect songSelect { get; set; }
[Resolved]
private Storage storage { get; set; }
[Resolved]
private RealmAccess realm { get; set; }
[Resolved(canBeNull: true)]
private INotificationOverlay notifications { get; set; }
public ITooltip<ScoreInfo> GetCustomTooltip() => new LeaderboardScoreTooltip();
public virtual ScoreInfo TooltipContent => Score;
private ScoreManager scoreManager = null!;
public LeaderboardScore(ScoreInfo score, int? rank, bool isOnlineScope = true)
{
Score = score;
@ -103,6 +93,8 @@ namespace osu.Game.Online.Leaderboards
statisticsLabels = GetStatistics(Score).Select(s => new ScoreComponentLabel(s)).ToList();
this.scoreManager = scoreManager;
ClickableAvatar innerAvatar;
Children = new Drawable[]
@ -434,7 +426,7 @@ namespace osu.Game.Online.Leaderboards
if (Score.Files.Count > 0)
{
items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => new LegacyScoreExporter(storage, realm, notifications).ExportAsync(Score))));
items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(Score)));
items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score))));
}

View File

@ -13,7 +13,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Database;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
@ -138,15 +137,6 @@ namespace osu.Game.Overlays.Settings.Sections
[Resolved]
private SkinManager skins { get; set; }
[Resolved]
private Storage storage { get; set; }
[Resolved]
private RealmAccess realm { get; set; }
[Resolved(canBeNull: true)]
private INotificationOverlay notifications { get; set; }
private Bindable<Skin> currentSkin;
[BackgroundDependencyLoader]
@ -168,7 +158,7 @@ namespace osu.Game.Overlays.Settings.Sections
{
try
{
currentSkin.Value.SkinInfo.PerformRead(s => new LegacySkinExporter(storage, realm, notifications).ExportAsync(s));
skins.ExporCurrenttSkin();
}
catch (Exception e)
{

View File

@ -27,6 +27,7 @@ namespace osu.Game.Scoring
{
private readonly OsuConfigManager configManager;
private readonly ScoreImporter scoreImporter;
private readonly LegacyScoreExporter scoreExporter;
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, RealmAccess realm, IAPIProvider api,
OsuConfigManager configManager = null)
@ -38,6 +39,11 @@ namespace osu.Game.Scoring
{
PostNotification = obj => PostNotification?.Invoke(obj)
};
scoreExporter = new LegacyScoreExporter(storage, realm)
{
PostNotification = obj => PostNotification?.Invoke(obj)
};
}
public Score GetScore(ScoreInfo score) => scoreImporter.GetScore(score);
@ -177,6 +183,8 @@ namespace osu.Game.Scoring
public Task<IEnumerable<Live<ScoreInfo>>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreImporter.Import(notification, tasks);
public void Export(ScoreInfo score) => Task.Run(() => scoreExporter.ExportAsync(score));
public Task<Live<ScoreInfo>> ImportAsUpdate(ProgressNotification notification, ImportTask task, ScoreInfo original) => scoreImporter.ImportAsUpdate(notification, task, original);
public Live<ScoreInfo> Import(ScoreInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) =>

View File

@ -6,7 +6,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework;
using osu.Framework.Allocation;
@ -21,7 +20,6 @@ using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Framework.Threading;
@ -30,7 +28,6 @@ using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
@ -89,12 +86,6 @@ namespace osu.Game.Screens.Edit
[Resolved]
private RulesetStore rulesets { get; set; }
[Resolved]
private Storage storage { get; set; }
[Resolved]
private RealmAccess realm { get; set; }
[Resolved(canBeNull: true)]
private IDialogOverlay dialogOverlay { get; set; }
@ -958,7 +949,7 @@ namespace osu.Game.Screens.Edit
private void exportBeatmap()
{
Save();
Task.Run(() => new LegacyBeatmapExporter(storage, realm, notifications).ExportAsync(Beatmap.Value.BeatmapSetInfo));
beatmapManager.Export(Beatmap.Value.BeatmapSetInfo);
}
/// <summary>

View File

@ -58,6 +58,8 @@ namespace osu.Game.Skinning
private readonly SkinImporter skinImporter;
private readonly LegacySkinExporter skinExporter;
private readonly IResourceStore<byte[]> userFiles;
private Skin argonSkin { get; }
@ -109,6 +111,11 @@ namespace osu.Game.Skinning
SourceChanged?.Invoke();
};
skinExporter = new LegacySkinExporter(storage, realm)
{
PostNotification = obj => PostNotification?.Invoke(obj)
};
}
public void SelectRandomSkin()
@ -280,6 +287,8 @@ namespace osu.Game.Skinning
public Task<Live<SkinInfo>> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinImporter.Import(task, batchImport, cancellationToken);
public void ExporCurrenttSkin() => CurrentSkinInfo.Value.PerformRead(s => skinExporter.ExportAsync(s));
#endregion
public void Delete([CanBeNull] Expression<Func<SkinInfo, bool>> filter = null, bool silent = false)