Db: Migrate ImportHistory to sqlite
This commit is contained in:
parent
7e2ccd3b42
commit
c7d5aa1eaa
@ -7,6 +7,8 @@ using System.Text.Json;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using ImGuiNET;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Pal.Client.Database;
|
||||
using NJson = Newtonsoft.Json;
|
||||
|
||||
namespace Pal.Client.Configuration
|
||||
@ -14,12 +16,14 @@ namespace Pal.Client.Configuration
|
||||
internal sealed class ConfigurationManager
|
||||
{
|
||||
private readonly DalamudPluginInterface _pluginInterface;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public event EventHandler<IPalacePalConfiguration>? Saved;
|
||||
|
||||
public ConfigurationManager(DalamudPluginInterface pluginInterface)
|
||||
public ConfigurationManager(DalamudPluginInterface pluginInterface, IServiceProvider serviceProvider)
|
||||
{
|
||||
_pluginInterface = pluginInterface;
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
Migrate();
|
||||
}
|
||||
@ -61,6 +65,26 @@ namespace Pal.Client.Configuration
|
||||
var v7 = MigrateToV7(configurationV1);
|
||||
Save(v7, queue: false);
|
||||
|
||||
using (var scope = _serviceProvider.CreateScope())
|
||||
{
|
||||
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
|
||||
dbContext.Imports.RemoveRange(dbContext.Imports);
|
||||
|
||||
foreach (var importHistory in configurationV1.ImportHistory)
|
||||
{
|
||||
PluginLog.Information($"Migrating import {importHistory.Id}");
|
||||
dbContext.Imports.Add(new ImportHistory
|
||||
{
|
||||
Id = importHistory.Id,
|
||||
RemoteUrl = importHistory.RemoteUrl?.Replace(".μ.tv", ".liza.sh"),
|
||||
ExportedAt = importHistory.ExportedAt,
|
||||
ImportedAt = importHistory.ImportedAt
|
||||
});
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
File.Move(_pluginInterface.ConfigFile.FullName, _pluginInterface.ConfigFile.FullName + ".old", true);
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,6 @@ namespace Pal.Client.Configuration
|
||||
DeepDungeonConfiguration DeepDungeons { get; set; }
|
||||
RendererConfiguration Renderer { get; set; }
|
||||
|
||||
[Obsolete]
|
||||
List<ConfigurationV1.ImportHistoryEntry> ImportHistory { get; }
|
||||
|
||||
IAccountConfiguration CreateAccount(string server, Guid accountId);
|
||||
IAccountConfiguration? FindAccount(string server);
|
||||
void RemoveAccount(string server);
|
||||
|
12
Pal.Client/Database/ImportHistory.cs
Normal file
12
Pal.Client/Database/ImportHistory.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Pal.Client.Database
|
||||
{
|
||||
internal sealed class ImportHistory
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? RemoteUrl { get; set; }
|
||||
public DateTime ExportedAt { get; set; }
|
||||
public DateTime ImportedAt { get; set; }
|
||||
}
|
||||
}
|
45
Pal.Client/Database/Migrations/20230216154417_AddImportHistory.Designer.cs
generated
Normal file
45
Pal.Client/Database/Migrations/20230216154417_AddImportHistory.Designer.cs
generated
Normal file
@ -0,0 +1,45 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Pal.Client.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Pal.Client.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(PalClientContext))]
|
||||
[Migration("20230216154417_AddImportHistory")]
|
||||
partial class AddImportHistory
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.3");
|
||||
|
||||
modelBuilder.Entity("Pal.Client.Database.ImportHistory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ExportedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RemoteUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Imports");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Pal.Client.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddImportHistory : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Imports",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||
RemoteUrl = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ExportedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
ImportedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Imports", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Imports");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Pal.Client.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Pal.Client.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(PalClientContext))]
|
||||
partial class PalClientContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.3");
|
||||
|
||||
modelBuilder.Entity("Pal.Client.Database.ImportHistory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ExportedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("ImportedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RemoteUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Imports");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
14
Pal.Client/Database/PalClientContext.cs
Normal file
14
Pal.Client/Database/PalClientContext.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Pal.Client.Database
|
||||
{
|
||||
internal class PalClientContext : DbContext
|
||||
{
|
||||
public DbSet<ImportHistory> Imports { get; set; } = null!;
|
||||
|
||||
public PalClientContext(DbContextOptions<PalClientContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
20
Pal.Client/Database/PalClientContextFactory.cs
Normal file
20
Pal.Client/Database/PalClientContextFactory.cs
Normal file
@ -0,0 +1,20 @@
|
||||
#if EF
|
||||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
|
||||
namespace Pal.Client.Database
|
||||
{
|
||||
internal sealed class PalClientContextFactory : IDesignTimeDbContextFactory<PalClientContext>
|
||||
{
|
||||
public PalClientContext CreateDbContext(string[] args)
|
||||
{
|
||||
var optionsBuilder =
|
||||
new DbContextOptionsBuilder<PalClientContext>().UseSqlite(
|
||||
$"Data Source={Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "XIVLauncher", "pluginConfigs", "Palace Pal", "palace-pal.data.sqlite3")}");
|
||||
return new PalClientContext(optionsBuilder.Options);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
58
Pal.Client/DependencyInjection/ImportService.cs
Normal file
58
Pal.Client/DependencyInjection/ImportService.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Pal.Client.Database;
|
||||
|
||||
namespace Pal.Client.DependencyInjection
|
||||
{
|
||||
internal sealed class ImportService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public ImportService(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void Add(ImportHistory history)
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
|
||||
|
||||
dbContext.Imports.Add(history);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public ImportHistory? FindLast()
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
|
||||
|
||||
return dbContext.Imports.OrderByDescending(x => x.ImportedAt).ThenBy(x => x.Id).FirstOrDefault();
|
||||
}
|
||||
|
||||
public List<ImportHistory> FindForServer(string server)
|
||||
{
|
||||
if (string.IsNullOrEmpty(server))
|
||||
return new();
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
|
||||
|
||||
return dbContext.Imports.Where(x => x.RemoteUrl == server).ToList();
|
||||
}
|
||||
|
||||
public void RemoveAllByIds(List<Guid> ids)
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
|
||||
|
||||
dbContext.RemoveRange(dbContext.Imports.Where(x => ids.Contains(x.Id)));
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public void RemoveById(Guid id)
|
||||
=> RemoveAllByIds(new List<Guid> { id });
|
||||
}
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
using System.Globalization;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
@ -7,17 +11,22 @@ using Dalamud.Game.ClientState.Objects;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Game.Gui;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Pal.Client.Commands;
|
||||
using Pal.Client.Configuration;
|
||||
using Pal.Client.Database;
|
||||
using Pal.Client.DependencyInjection;
|
||||
using Pal.Client.Net;
|
||||
using Pal.Client.Properties;
|
||||
using Pal.Client.Rendering;
|
||||
using Pal.Client.Scheduled;
|
||||
using Pal.Client.Windows;
|
||||
|
||||
namespace Pal.Client.DependencyInjection
|
||||
namespace Pal.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// DI-aware Plugin.
|
||||
@ -25,6 +34,8 @@ namespace Pal.Client.DependencyInjection
|
||||
// ReSharper disable once UnusedType.Global
|
||||
internal sealed class DependencyInjectionContext : IDalamudPlugin
|
||||
{
|
||||
private readonly string _sqliteConnectionString;
|
||||
private readonly CancellationTokenSource _initCts = new();
|
||||
private ServiceProvider? _serviceProvider;
|
||||
|
||||
public string Name => Localization.Palace_Pal;
|
||||
@ -39,6 +50,9 @@ namespace Pal.Client.DependencyInjection
|
||||
CommandManager commandManager,
|
||||
DataManager dataManager)
|
||||
{
|
||||
PluginLog.Information("Building service container");
|
||||
|
||||
CancellationToken token = _initCts.Token;
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
// dalamud
|
||||
@ -54,6 +68,11 @@ namespace Pal.Client.DependencyInjection
|
||||
services.AddSingleton(dataManager);
|
||||
services.AddSingleton(new WindowSystem(typeof(DependencyInjectionContext).AssemblyQualifiedName));
|
||||
|
||||
// EF core
|
||||
_sqliteConnectionString =
|
||||
$"Data Source={Path.Join(pluginInterface.GetPluginConfigDirectory(), "palace-pal.data.sqlite3")}";
|
||||
services.AddDbContext<PalClientContext>(o => o.UseSqlite(_sqliteConnectionString));
|
||||
|
||||
// plugin-specific
|
||||
services.AddSingleton<Plugin>();
|
||||
services.AddSingleton<DebugState>();
|
||||
@ -64,11 +83,12 @@ namespace Pal.Client.DependencyInjection
|
||||
services.AddTransient<RepoVerification>();
|
||||
services.AddSingleton<PalCommand>();
|
||||
|
||||
// territory handling
|
||||
// territory & marker related services
|
||||
services.AddSingleton<TerritoryState>();
|
||||
services.AddSingleton<FrameworkService>();
|
||||
services.AddSingleton<ChatService>();
|
||||
services.AddSingleton<FloorService>();
|
||||
services.AddSingleton<ImportService>();
|
||||
|
||||
// windows & related services
|
||||
services.AddSingleton<AgreementWindow>();
|
||||
@ -97,7 +117,7 @@ namespace Pal.Client.DependencyInjection
|
||||
ValidateScopes = true,
|
||||
});
|
||||
|
||||
// initialize plugin
|
||||
|
||||
#if RELEASE
|
||||
// You're welcome to remove this code in your fork, but please make sure that:
|
||||
// - none of the links accessible within FFXIV open the original repo (e.g. in the plugin installer), and
|
||||
@ -108,24 +128,61 @@ namespace Pal.Client.DependencyInjection
|
||||
_serviceProvider.GetService<RepoVerification>();
|
||||
#endif
|
||||
|
||||
// set up legacy services
|
||||
LocalState.PluginInterface = pluginInterface;
|
||||
LocalState.Mode = _serviceProvider.GetRequiredService<IPalacePalConfiguration>().Mode;
|
||||
// This is not ideal as far as loading the plugin goes, because there's no way to check for errors and
|
||||
// tell Dalamud that no, the plugin isn't ready -- so the plugin will count as properly initialized,
|
||||
// even if it's not.
|
||||
//
|
||||
// There's 2-3 seconds of slowdown primarily caused by the sqlite init, but that needs to happen for
|
||||
// config stuff.
|
||||
PluginLog.Information("Service container built, triggering async init");
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
PluginLog.Information("Starting async init");
|
||||
|
||||
// windows that have logic to open on startup
|
||||
_serviceProvider.GetRequiredService<AgreementWindow>();
|
||||
// initialize database
|
||||
await using (var scope = _serviceProvider.CreateAsyncScope())
|
||||
{
|
||||
PluginLog.Log("Loading database & running migrations");
|
||||
await using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
|
||||
await dbContext.Database.MigrateAsync();
|
||||
|
||||
// initialize components that are mostly self-contained/self-registered
|
||||
_serviceProvider.GetRequiredService<Hooks>();
|
||||
_serviceProvider.GetRequiredService<PalCommand>();
|
||||
_serviceProvider.GetRequiredService<FrameworkService>();
|
||||
_serviceProvider.GetRequiredService<ChatService>();
|
||||
PluginLog.Log("Completed database migrations");
|
||||
}
|
||||
|
||||
_serviceProvider.GetRequiredService<Plugin>();
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
// set up legacy services
|
||||
LocalState.PluginConfigDirectory = pluginInterface.GetPluginConfigDirectory();
|
||||
LocalState.Mode = _serviceProvider.GetRequiredService<IPalacePalConfiguration>().Mode;
|
||||
|
||||
// windows that have logic to open on startup
|
||||
_serviceProvider.GetRequiredService<AgreementWindow>();
|
||||
|
||||
// initialize components that are mostly self-contained/self-registered
|
||||
_serviceProvider.GetRequiredService<Hooks>();
|
||||
_serviceProvider.GetRequiredService<PalCommand>();
|
||||
_serviceProvider.GetRequiredService<FrameworkService>();
|
||||
_serviceProvider.GetRequiredService<ChatService>();
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
_serviceProvider.GetRequiredService<Plugin>();
|
||||
|
||||
PluginLog.Information("Async init complete");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error(e, "Async load failed");
|
||||
chatGui.PrintError($"Async loading failed: {e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_initCts.Cancel();
|
||||
|
||||
// ensure we're not calling dispose recursively on ourselves
|
||||
if (_serviceProvider != null)
|
||||
{
|
||||
@ -133,6 +190,10 @@ namespace Pal.Client.DependencyInjection
|
||||
_serviceProvider = null;
|
||||
|
||||
serviceProvider.Dispose();
|
||||
|
||||
// ensure we're not keeping the file open longer than the plugin is loaded
|
||||
using (SqliteConnection sqliteConnection = new(_sqliteConnectionString))
|
||||
SqliteConnection.ClearPool(sqliteConnection);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Dalamud.Plugin;
|
||||
using Pal.Client.Configuration;
|
||||
using Pal.Client.Extensions;
|
||||
|
||||
@ -19,7 +18,7 @@ namespace Pal.Client
|
||||
private static readonly JsonSerializerOptions JsonSerializerOptions = new() { IncludeFields = true };
|
||||
private const int CurrentVersion = 4;
|
||||
|
||||
internal static DalamudPluginInterface PluginInterface { get; set; }
|
||||
internal static string PluginConfigDirectory { get; set; } = null!;
|
||||
internal static EMode Mode { get; set; }
|
||||
|
||||
public uint TerritoryType { get; set; }
|
||||
@ -126,7 +125,7 @@ namespace Pal.Client
|
||||
|
||||
public string GetSaveLocation() => GetSaveLocation(TerritoryType);
|
||||
|
||||
private static string GetSaveLocation(uint territoryType) => Path.Join(PluginInterface.GetPluginConfigDirectory(), $"{territoryType}.json");
|
||||
private static string GetSaveLocation(uint territoryType) => Path.Join(PluginConfigDirectory, $"{territoryType}.json");
|
||||
|
||||
public static void ForEach(Action<LocalState> action)
|
||||
{
|
||||
|
@ -25,15 +25,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')">
|
||||
<None Remove="Certificate.pfx" />
|
||||
<None Remove="Certificate.pfx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')">
|
||||
<EmbeddedResource Include="Certificate.pfx" />
|
||||
<EmbeddedResource Update="Properties\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Certificate.pfx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -68,44 +64,51 @@
|
||||
<!--You may need to adjust these paths yourself. These point to a Dalamud assembly in AppData.-->
|
||||
<Reference Include="Dalamud">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Dalamud.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGui.NET">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImGuiScene">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Lumina.Excel">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
<Reference Include="FFXIVClientStructs">
|
||||
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\FFXIVClientStructs.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<Private Condition="'$(Configuration)' != 'EF'">false</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Localization.resx</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="Properties\Localization.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<Compile Update="Properties\Localization.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Localization.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="RenameLatestZip" AfterTargets="PackagePlugin">
|
||||
<Target Name="RenameLatestZip" AfterTargets="PackagePlugin" Condition="'$(Configuration)' == 'Release'">
|
||||
<Exec Command="rename "$(OutDir)$(AssemblyName)\latest.zip" "$(AssemblyName)-$(Version).zip"" />
|
||||
</Target>
|
||||
|
||||
<Target Name="Clean">
|
||||
<RemoveDir Directories="dist" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
@ -6,4 +6,4 @@
|
||||
"RepoUrl": "https://github.com/carvelli/PalacePal",
|
||||
"IconUrl": "https://raw.githubusercontent.com/carvelli/Dalamud-Plugins/master/dist/Palace Pal.png",
|
||||
"Tags": [ "potd", "palace", "hoh", "splatoon" ]
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ using Pal.Client.Windows;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Dalamud.Logging;
|
||||
using Pal.Client.Properties;
|
||||
using ECommons;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -31,8 +30,6 @@ namespace Pal.Client
|
||||
IPalacePalConfiguration configuration,
|
||||
RenderAdapter renderAdapter)
|
||||
{
|
||||
PluginLog.Information("Initializing Palace Pal");
|
||||
|
||||
_serviceProvider = serviceProvider;
|
||||
_pluginInterface = pluginInterface;
|
||||
_configuration = configuration;
|
||||
|
15
Pal.Client/README.md
Normal file
15
Pal.Client/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Palace Pal
|
||||
|
||||
## Client Build Notes
|
||||
|
||||
### Database Migrations
|
||||
|
||||
Since EF core needs all dll files to be present, including Dalamud ones,
|
||||
there's a special `EF` configuration that exempts them from setting
|
||||
`<Private>false</Private>` during the build.
|
||||
|
||||
To use with `dotnet ef` commands, specify it as `-c EF`, for example:
|
||||
|
||||
```shell
|
||||
dotnet ef migrations add MigrationName --configuration EF
|
||||
```
|
@ -7,10 +7,11 @@ using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.Gui;
|
||||
using Dalamud.Logging;
|
||||
using Pal.Client.Configuration;
|
||||
using Pal.Client.Database;
|
||||
using Pal.Client.DependencyInjection;
|
||||
using Pal.Client.Extensions;
|
||||
using Pal.Client.Properties;
|
||||
using Pal.Client.Windows;
|
||||
|
||||
namespace Pal.Client.Scheduled
|
||||
{
|
||||
@ -30,17 +31,20 @@ namespace Pal.Client.Scheduled
|
||||
internal sealed class Handler : IQueueOnFrameworkThread.Handler<QueuedImport>
|
||||
{
|
||||
private readonly ChatGui _chatGui;
|
||||
private readonly IPalacePalConfiguration _configuration;
|
||||
private readonly ConfigurationManager _configurationManager;
|
||||
private readonly FloorService _floorService;
|
||||
private readonly ImportService _importService;
|
||||
private readonly ConfigWindow _configWindow;
|
||||
|
||||
public Handler(ChatGui chatGui, IPalacePalConfiguration configuration,
|
||||
ConfigurationManager configurationManager, FloorService floorService)
|
||||
public Handler(
|
||||
ChatGui chatGui,
|
||||
FloorService floorService,
|
||||
ImportService importService,
|
||||
ConfigWindow configWindow)
|
||||
{
|
||||
_chatGui = chatGui;
|
||||
_configuration = configuration;
|
||||
_configurationManager = configurationManager;
|
||||
_floorService = floorService;
|
||||
_importService = importService;
|
||||
_configWindow = configWindow;
|
||||
}
|
||||
|
||||
protected override void Run(QueuedImport import, ref bool recreateLayout, ref bool saveMarkers)
|
||||
@ -53,11 +57,9 @@ namespace Pal.Client.Scheduled
|
||||
if (!Validate(import))
|
||||
return;
|
||||
|
||||
var oldExportIds = string.IsNullOrEmpty(import.Export.ServerUrl)
|
||||
? _configuration.ImportHistory.Where(x => x.RemoteUrl == import.Export.ServerUrl)
|
||||
.Select(x => x.Id)
|
||||
.Where(x => x != Guid.Empty).ToList()
|
||||
: new List<Guid>();
|
||||
List<Guid> oldExportIds = _importService.FindForServer(import.Export.ServerUrl)
|
||||
.Select(x => x.Id)
|
||||
.ToList();
|
||||
|
||||
foreach (var remoteFloor in import.Export.Floors)
|
||||
{
|
||||
@ -70,17 +72,19 @@ namespace Pal.Client.Scheduled
|
||||
localState.Save();
|
||||
}
|
||||
|
||||
_configuration.ImportHistory.RemoveAll(hist =>
|
||||
oldExportIds.Contains(hist.Id) || hist.Id == import.ExportId);
|
||||
_configuration.ImportHistory.Add(new ConfigurationV1.ImportHistoryEntry
|
||||
_importService.RemoveAllByIds(oldExportIds);
|
||||
_importService.RemoveById(import.ExportId);
|
||||
_importService.Add(new ImportHistory
|
||||
{
|
||||
Id = import.ExportId,
|
||||
RemoteUrl = import.Export.ServerUrl,
|
||||
ExportedAt = import.Export.CreatedAt.ToDateTime(),
|
||||
ImportedAt = DateTime.UtcNow,
|
||||
});
|
||||
_configurationManager.Save(_configuration);
|
||||
_configWindow.UpdateLastImport();
|
||||
|
||||
PluginLog.Information(
|
||||
$"Imported {import.ExportId} for {import.ImportedTraps} traps, {import.ImportedHoardCoffers} hoard coffers");
|
||||
_chatGui.PalMessage(string.Format(Localization.ImportCompleteStatistics, import.ImportedTraps,
|
||||
import.ImportedHoardCoffers));
|
||||
}
|
||||
@ -101,9 +105,9 @@ namespace Pal.Client.Scheduled
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Guid.TryParse(import.Export.ExportId, out Guid exportId) || import.ExportId == Guid.Empty)
|
||||
if (!Guid.TryParse(import.Export.ExportId, out Guid exportId) || exportId == Guid.Empty)
|
||||
{
|
||||
PluginLog.Error("Import: Invalid export id");
|
||||
PluginLog.Error($"Import: Invalid export id ({import.Export.ExportId})");
|
||||
_chatGui.PalError(Localization.Error_ImportFailed_InvalidFile);
|
||||
return false;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Pal.Client.Configuration;
|
||||
using Pal.Client.DependencyInjection;
|
||||
using Pal.Client.Windows;
|
||||
using Pal.Common;
|
||||
|
||||
namespace Pal.Client.Scheduled
|
||||
@ -17,13 +18,15 @@ namespace Pal.Client.Scheduled
|
||||
|
||||
internal sealed class Handler : IQueueOnFrameworkThread.Handler<QueuedUndoImport>
|
||||
{
|
||||
private readonly IPalacePalConfiguration _configuration;
|
||||
private readonly ImportService _importService;
|
||||
private readonly FloorService _floorService;
|
||||
private readonly ConfigWindow _configWindow;
|
||||
|
||||
public Handler(IPalacePalConfiguration configuration, FloorService floorService)
|
||||
public Handler(ImportService importService, FloorService floorService, ConfigWindow configWindow)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_importService = importService;
|
||||
_floorService = floorService;
|
||||
_configWindow = configWindow;
|
||||
}
|
||||
|
||||
protected override void Run(QueuedUndoImport queued, ref bool recreateLayout, ref bool saveMarkers)
|
||||
@ -38,7 +41,8 @@ namespace Pal.Client.Scheduled
|
||||
localState.Save();
|
||||
}
|
||||
|
||||
_configuration.ImportHistory.RemoveAll(hist => hist.Id == queued.ExportId);
|
||||
_importService.RemoveById(queued.ExportId);
|
||||
_configWindow.UpdateLastImport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ using System.Threading.Tasks;
|
||||
using Dalamud.Game.Gui;
|
||||
using Pal.Client.Properties;
|
||||
using Pal.Client.Configuration;
|
||||
using Pal.Client.Database;
|
||||
using Pal.Client.DependencyInjection;
|
||||
using Pal.Client.Extensions;
|
||||
|
||||
@ -40,6 +41,7 @@ namespace Pal.Client.Windows
|
||||
private readonly DebugState _debugState;
|
||||
private readonly ChatGui _chatGui;
|
||||
private readonly RemoteApi _remoteApi;
|
||||
private readonly ImportService _importService;
|
||||
|
||||
private int _mode;
|
||||
private int _renderer;
|
||||
@ -55,6 +57,7 @@ namespace Pal.Client.Windows
|
||||
private string? _saveExportDialogStartPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
private readonly FileDialogManager _importDialog;
|
||||
private readonly FileDialogManager _exportDialog;
|
||||
private ImportHistory? _lastImport;
|
||||
|
||||
private CancellationTokenSource? _testConnectionCts;
|
||||
|
||||
@ -68,7 +71,8 @@ namespace Pal.Client.Windows
|
||||
FloorService floorService,
|
||||
DebugState debugState,
|
||||
ChatGui chatGui,
|
||||
RemoteApi remoteApi)
|
||||
RemoteApi remoteApi,
|
||||
ImportService importService)
|
||||
: base(WindowId)
|
||||
{
|
||||
_windowSystem = windowSystem;
|
||||
@ -81,6 +85,7 @@ namespace Pal.Client.Windows
|
||||
_debugState = debugState;
|
||||
_chatGui = chatGui;
|
||||
_remoteApi = remoteApi;
|
||||
_importService = importService;
|
||||
|
||||
LanguageChanged();
|
||||
|
||||
@ -117,6 +122,8 @@ namespace Pal.Client.Windows
|
||||
_hoardConfig = new ConfigurableMarker(_configuration.DeepDungeons.HoardCoffers);
|
||||
_silverConfig = new ConfigurableMarker(_configuration.DeepDungeons.SilverCoffers);
|
||||
_connectionText = null;
|
||||
|
||||
UpdateLastImport();
|
||||
}
|
||||
|
||||
public override void OnClose()
|
||||
@ -278,13 +285,14 @@ namespace Pal.Client.Windows
|
||||
DoImport(_openImportPath);
|
||||
ImGui.EndDisabled();
|
||||
|
||||
var importHistory = _configuration.ImportHistory.OrderByDescending(x => x.ImportedAt)
|
||||
.ThenBy(x => x.Id).FirstOrDefault();
|
||||
ImportHistory? importHistory = _lastImport;
|
||||
if (importHistory != null)
|
||||
{
|
||||
ImGui.Separator();
|
||||
ImGui.TextWrapped(string.Format(Localization.Config_UndoImportExplanation1,
|
||||
importHistory.ImportedAt, importHistory.RemoteUrl, importHistory.ExportedAt));
|
||||
importHistory.ImportedAt.ToLocalTime(),
|
||||
importHistory.RemoteUrl,
|
||||
importHistory.ExportedAt.ToUniversalTime()));
|
||||
ImGui.TextWrapped(Localization.Config_UndoImportExplanation2);
|
||||
if (ImGui.Button(Localization.Config_UndoImport))
|
||||
UndoImport(importHistory.Id);
|
||||
@ -466,6 +474,11 @@ namespace Pal.Client.Windows
|
||||
_frameworkService.EarlyEventQueue.Enqueue(new QueuedUndoImport(importId));
|
||||
}
|
||||
|
||||
internal void UpdateLastImport()
|
||||
{
|
||||
_lastImport = _importService.FindLast();
|
||||
}
|
||||
|
||||
private void DoExport(string destinationPath)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
|
Loading…
Reference in New Issue
Block a user