mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Add Upload support to WJ, fixes for the new server, etc.
This commit is contained in:
parent
a206b833b5
commit
6969a531e2
@ -13,5 +13,8 @@ namespace Wabbajack.BuildServer
|
||||
public string ArchiveDir { get; set; }
|
||||
|
||||
public bool MinimalMode { get; set; }
|
||||
|
||||
public bool RunFrontEndJobs { get; set; }
|
||||
public bool RunBackEndJobs { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using GraphQL;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using Wabbajack.BuildServer.Models;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack.BuildServer.Controllers
|
||||
{
|
||||
@ -15,5 +22,7 @@ namespace Wabbajack.BuildServer.Controllers
|
||||
Db = db;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,9 @@ namespace Wabbajack.BuildServer.Controllers
|
||||
public async Task<IActionResult> UploadFile(IList<IFormFile> files)
|
||||
{
|
||||
var user = User.FindFirstValue(ClaimTypes.Name);
|
||||
foreach (var file in files)
|
||||
await UploadedFile.Ingest(Db, file, user);
|
||||
|
||||
return Ok();
|
||||
UploadedFile result = null;
|
||||
result = await UploadedFile.Ingest(Db, files.First(), user);
|
||||
return Ok(result.Uri.ToString());
|
||||
}
|
||||
|
||||
private static readonly Func<object, string> HandleGetListTemplate = NettleEngine.GetCompiler().Compile(@"
|
||||
|
58
Wabbajack.BuildServer/Controllers/Users.cs
Normal file
58
Wabbajack.BuildServer/Controllers/Users.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
using Wabbajack.BuildServer.Models;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack.BuildServer.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
[Route("/users")]
|
||||
public class Users : AControllerBase<Users>
|
||||
{
|
||||
public Users(ILogger<Users> logger, DBContext db) : base(logger, db)
|
||||
{
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("add/{Name}")]
|
||||
public async Task<string> AddUser(string Name)
|
||||
{
|
||||
var user = new ApiKey();
|
||||
var arr = new byte[128];
|
||||
new Random().NextBytes(arr);
|
||||
user.Owner = Name;
|
||||
user.Key = arr.ToHex();
|
||||
user.Id = Guid.NewGuid().ToString();
|
||||
user.Roles = new List<string>();
|
||||
user.CanUploadLists = new List<string>();
|
||||
|
||||
await Db.ApiKeys.InsertOneAsync(user);
|
||||
|
||||
return user.Id;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("/export")]
|
||||
public async Task<string> Export()
|
||||
{
|
||||
if (!Directory.Exists("exported_users"))
|
||||
Directory.CreateDirectory("exported_users");
|
||||
|
||||
foreach (var user in await Db.ApiKeys.AsQueryable().ToListAsync())
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine("exported_users", user.Owner));
|
||||
Alphaleonis.Win32.Filesystem.File.WriteAllText(Path.Combine("exported_users", user.Owner, "author-api-key.txt"), user.Key);
|
||||
}
|
||||
|
||||
return "done";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -106,6 +106,8 @@ namespace Wabbajack.BuildServer
|
||||
|
||||
private async Task ScheduledJob<T>(TimeSpan span, Job.JobPriority priority) where T : AJobPayload, new()
|
||||
{
|
||||
if (!Settings.RunBackEndJobs && typeof(T).IsSubclassOf(typeof(IBackEndJob))) return;
|
||||
if (!Settings.RunFrontEndJobs && typeof(T).IsSubclassOf(typeof(IFrontEndJob))) return;
|
||||
try
|
||||
{
|
||||
var jobs = await Db.Jobs.AsQueryable()
|
||||
|
@ -12,7 +12,7 @@ using Wabbajack.Lib.ModListRegistry;
|
||||
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public class EnqueueAllArchives : AJobPayload
|
||||
public class EnqueueAllArchives : AJobPayload, IBackEndJob
|
||||
{
|
||||
public override string Description => "Add missing modlist archives to indexer";
|
||||
public override async Task<JobResult> Execute(DBContext db, AppSettings settings)
|
||||
|
@ -12,7 +12,7 @@ using Path = Alphaleonis.Win32.Filesystem.Path;
|
||||
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public class EnqueueAllGameFiles : AJobPayload
|
||||
public class EnqueueAllGameFiles : AJobPayload, IBackEndJob
|
||||
{
|
||||
public override string Description { get => $"Enqueue all game files for indexing"; }
|
||||
public override async Task<JobResult> Execute(DBContext db, AppSettings settings)
|
||||
|
@ -13,7 +13,7 @@ using Wabbajack.Lib.NexusApi;
|
||||
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public class EnqueueRecentFiles : AJobPayload
|
||||
public class EnqueueRecentFiles : AJobPayload, IFrontEndJob
|
||||
{
|
||||
public override string Description => "Enqueue the past days worth of mods for indexing";
|
||||
|
||||
|
@ -10,7 +10,7 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public class GetNexusUpdatesJob : AJobPayload
|
||||
public class GetNexusUpdatesJob : AJobPayload, IFrontEndJob
|
||||
{
|
||||
public override string Description => "Poll the Nexus for updated mods, and clean any references to those mods";
|
||||
|
||||
|
7
Wabbajack.BuildServer/Models/Jobs/IBackEndJob.cs
Normal file
7
Wabbajack.BuildServer/Models/Jobs/IBackEndJob.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public interface IBackEndJob
|
||||
{
|
||||
|
||||
}
|
||||
}
|
7
Wabbajack.BuildServer/Models/Jobs/IFrontEndJob.cs
Normal file
7
Wabbajack.BuildServer/Models/Jobs/IFrontEndJob.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public interface IFrontEndJob
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ using Wabbajack.VirtualFileSystem;
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
|
||||
public class IndexJob : AJobPayload
|
||||
public class IndexJob : AJobPayload, IBackEndJob
|
||||
{
|
||||
public Archive Archive { get; set; }
|
||||
public override string Description => $"Index ${Archive.State.PrimaryKeyString} and save the download/file state";
|
||||
|
@ -12,7 +12,7 @@ using File = Alphaleonis.Win32.Filesystem.File;
|
||||
|
||||
namespace Wabbajack.BuildServer.Models.Jobs
|
||||
{
|
||||
public class UpdateModLists : AJobPayload
|
||||
public class UpdateModLists : AJobPayload, IFrontEndJob
|
||||
{
|
||||
public override string Description => "Validate curated modlists";
|
||||
public override async Task<JobResult> Execute(DBContext db, AppSettings settings)
|
||||
@ -26,7 +26,7 @@ namespace Wabbajack.BuildServer.Models.Jobs
|
||||
var whitelists = new ValidateModlist(queue);
|
||||
await whitelists.LoadListsFromGithub();
|
||||
|
||||
foreach (var list in modlists.Skip(8).Take(1))
|
||||
foreach (var list in modlists)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -18,15 +18,14 @@ namespace Wabbajack.BuildServer.Models
|
||||
public DateTime UploadDate { get; set; } = DateTime.UtcNow;
|
||||
|
||||
[BsonIgnore]
|
||||
public string MungedName => $"{Path.GetFileNameWithoutExtension(Name)}-{Id}-{Path.GetExtension(Name)}";
|
||||
public string MungedName => $"{Path.GetFileNameWithoutExtension(Name)}-{Id}{Path.GetExtension(Name)}";
|
||||
|
||||
[BsonIgnore] public object Uri => $"https://static.wabbajack.org/files/{MungedName}";
|
||||
[BsonIgnore] public object Uri => $"https://build.wabbajack.org/files/{MungedName}";
|
||||
|
||||
public static async Task<UploadedFile> Ingest(DBContext db, IFormFile src, string uploader)
|
||||
{
|
||||
var record = new UploadedFile {Uploader = uploader, Name = src.FileName, Id = Guid.NewGuid().ToString()};
|
||||
var dest_path =
|
||||
$@"public\\files\\{Path.GetFileNameWithoutExtension(src.FileName)}-{record.Id}{Path.GetExtension(src.FileName)}";
|
||||
var dest_path = $@"public\\files\\{record.MungedName}";
|
||||
|
||||
using (var stream = File.OpenWrite(dest_path))
|
||||
await src.CopyToAsync(stream);
|
||||
|
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -20,10 +22,20 @@ namespace Wabbajack.BuildServer
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseUrls("http://*:5000");
|
||||
webBuilder.UseStartup<Startup>()
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
options.Listen(IPAddress.Any, 80);
|
||||
options.Listen(IPAddress.Any, 443, listenOptions =>
|
||||
{
|
||||
using (var store = new X509Store(StoreName.My))
|
||||
{
|
||||
store.Open(OpenFlags.ReadOnly);
|
||||
var cert = store.Certificates.Find(X509FindType.FindBySubjectName, "build.wabbajack.org", true)[0];
|
||||
listenOptions.UseHttps(cert);
|
||||
|
||||
}
|
||||
});
|
||||
options.Limits.MaxRequestBodySize = null;
|
||||
});
|
||||
});
|
||||
|
@ -11,9 +11,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
@ -88,7 +86,7 @@ namespace Wabbajack.BuildServer
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseGraphiQl();
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseStaticFiles();
|
||||
|
@ -12,10 +12,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="graphiql" Version="1.2.0" />
|
||||
<PackageReference Include="GraphQL" Version="3.0.0-preview-1352" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
||||
|
@ -32,7 +32,9 @@
|
||||
"WabbajackSettings": {
|
||||
"DownloadDir": "c:\\tmp\\downloads",
|
||||
"ArchiveDir": "c:\\archives",
|
||||
"MinimalMode": true
|
||||
"MinimalMode": true,
|
||||
"RunFrontEndJobs": true,
|
||||
"RunBackEndJobs": true
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
@ -6,9 +6,11 @@ namespace Wabbajack.Common
|
||||
{
|
||||
private string _message;
|
||||
private Stream _inner;
|
||||
private WorkQueue _queue;
|
||||
|
||||
public StatusFileStream(Stream fs, string message)
|
||||
public StatusFileStream(Stream fs, string message, WorkQueue queue = null)
|
||||
{
|
||||
_queue = queue;
|
||||
_inner = fs;
|
||||
_message = message;
|
||||
}
|
||||
@ -36,7 +38,14 @@ namespace Wabbajack.Common
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
if (_inner.Length != 0)
|
||||
if (_inner.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_queue != null)
|
||||
_queue.Report(_message, (int) (_inner.Position * 100 / _inner.Length));
|
||||
else
|
||||
Utils.Status(_message, (int) (_inner.Position * 100 / _inner.Length));
|
||||
}
|
||||
|
||||
|
22
Wabbajack.Lib/FileUploader/AuthorAPI.cs
Normal file
22
Wabbajack.Lib/FileUploader/AuthorAPI.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Reactive.Linq;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack.Lib.FileUploader
|
||||
{
|
||||
public class AuthorAPI
|
||||
{
|
||||
public static IObservable<bool> HaveAuthorAPIKey => Utils.HaveEncryptedJsonObservable("author-api-key");
|
||||
|
||||
public static IObservable<string> AuthorAPIKey => HaveAuthorAPIKey.Where(h => h)
|
||||
.Select(_ => File.ReadAllText(Path.Combine(Consts.LocalAppDataPath, "author-api-key")));
|
||||
|
||||
|
||||
public static string GetAPIKey()
|
||||
{
|
||||
return File.ReadAllText(Path.Combine(Consts.LocalAppDataPath, "author-api-key.txt")).Trim();
|
||||
}
|
||||
public static bool HasAPIKey => File.Exists(Path.Combine(Consts.LocalAppDataPath, "author-api-key.txt"));
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using GraphQL.Client;
|
||||
using GraphQL.Client.Http;
|
||||
using GraphQL.Common.Request;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.FileUploader;
|
||||
using Wabbajack.Lib.GraphQL.DTOs;
|
||||
using Path = Alphaleonis.Win32.Filesystem.Path;
|
||||
|
||||
@ -17,7 +20,7 @@ namespace Wabbajack.Lib.GraphQL
|
||||
public static readonly Uri BaseURL = new Uri("https://build.wabbajack.org/graphql");
|
||||
public static readonly Uri UploadURL = new Uri("https://build.wabbajack.org/upload_file");
|
||||
|
||||
public async Task<List<UploadedFile>> GetUploadedFiles()
|
||||
public static async Task<List<UploadedFile>> GetUploadedFiles()
|
||||
{
|
||||
var client = new GraphQLHttpClient(BaseURL);
|
||||
var query = new GraphQLRequest
|
||||
@ -38,16 +41,31 @@ namespace Wabbajack.Lib.GraphQL
|
||||
return result.GetDataFieldAs<List<UploadedFile>>("uploadedFiles");
|
||||
}
|
||||
|
||||
public async Task<bool> UploadFile(string filename)
|
||||
public static Task<string> UploadFile(WorkQueue queue, string filename)
|
||||
{
|
||||
using (var stream = new StatusFileStream(File.OpenRead(filename), $"Uploading {Path.GetFileName(filename)}"))
|
||||
var tcs = new TaskCompletionSource<string>();
|
||||
queue.QueueTask(async () =>
|
||||
{
|
||||
var client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Add("X-API-KEY", "TODO");
|
||||
var form = new MultipartFormDataContent {{new StreamContent(stream), "file"}};
|
||||
var response = await client.PostAsync(UploadURL, form);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
using (var stream =
|
||||
new StatusFileStream(File.OpenRead(filename), $"Uploading {Path.GetFileName(filename)}", queue))
|
||||
{
|
||||
var client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Add("X-API-KEY", AuthorAPI.GetAPIKey());
|
||||
var content = new StreamContent(stream);
|
||||
var form = new MultipartFormDataContent
|
||||
{
|
||||
{content, "files", Path.GetFileName(filename)}
|
||||
};
|
||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
|
||||
var response = await client.PostAsync(UploadURL, form);
|
||||
if (response.IsSuccessStatusCode)
|
||||
tcs.SetResult(await response.Content.ReadAsStringAsync());
|
||||
else
|
||||
tcs.SetResult("FAILED");
|
||||
}
|
||||
});
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
58
Wabbajack/View Models/Settings/AuthorFilesVM.cs
Normal file
58
Wabbajack/View Models/Settings/AuthorFilesVM.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using System.Windows;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.FileUploader;
|
||||
using Wabbajack.Lib.GraphQL;
|
||||
using Wabbajack.Lib.GraphQL.DTOs;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public class AuthorFilesVM : BackNavigatingVM
|
||||
{
|
||||
public Visibility IsVisible { get; }
|
||||
|
||||
[Reactive]
|
||||
public string SelectedFile { get; set; }
|
||||
|
||||
public IReactiveCommand SelectFile { get; }
|
||||
public IReactiveCommand Upload { get; }
|
||||
|
||||
[Reactive]
|
||||
public double UploadProgress { get; set; }
|
||||
|
||||
private WorkQueue Queue = new WorkQueue(1);
|
||||
|
||||
public AuthorFilesVM(SettingsVM vm) : base(vm.MWVM)
|
||||
{
|
||||
var sub = new Subject<double>();
|
||||
Queue.Status.Select(s => (double)s.ProgressPercent).Subscribe(v =>
|
||||
{
|
||||
UploadProgress = v;
|
||||
});
|
||||
IsVisible = AuthorAPI.HasAPIKey ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
SelectFile = ReactiveCommand.Create(() =>
|
||||
{
|
||||
var fod = UIUtils.OpenFileDialog("*|*");
|
||||
if (fod != null)
|
||||
SelectedFile = fod;
|
||||
});
|
||||
|
||||
Upload = ReactiveCommand.Create(async () =>
|
||||
{
|
||||
SelectedFile = await GraphQLService.UploadFile(Queue, SelectedFile);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -14,12 +14,16 @@ namespace Wabbajack
|
||||
public LoginManagerVM Login { get; }
|
||||
public PerformanceSettings Performance { get; }
|
||||
|
||||
public AuthorFilesVM AuthorFile { get; }
|
||||
|
||||
public SettingsVM(MainWindowVM mainWindowVM)
|
||||
: base(mainWindowVM)
|
||||
{
|
||||
MWVM = mainWindowVM;
|
||||
Login = new LoginManagerVM(this);
|
||||
Performance = mainWindowVM.Settings.Performance;
|
||||
AuthorFile = new AuthorFilesVM(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
ResizeMode="CanResize"
|
||||
Style="{StaticResource {x:Type Window}}"
|
||||
TitleBarHeight="25"
|
||||
TitlebarHeight="25"
|
||||
UseLayoutRounding="True"
|
||||
WindowStyle="ToolWindow"
|
||||
mc:Ignorable="d">
|
||||
|
45
Wabbajack/Views/Settings/AuthorFilesView.xaml
Normal file
45
Wabbajack/Views/Settings/AuthorFilesView.xaml
Normal file
@ -0,0 +1,45 @@
|
||||
<rxui:ReactiveUserControl
|
||||
x:Class="Wabbajack.AuthorFilesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Wabbajack"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:rxui="http://reactiveui.net"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:TypeArguments="local:AuthorFilesVM"
|
||||
mc:Ignorable="d">
|
||||
<Border
|
||||
|
||||
Visibility="{Binding AuthorFile.IsVisible}"
|
||||
x:Name="AuthorFiles"
|
||||
Margin="5"
|
||||
Background="{StaticResource BackgroundBrush}"
|
||||
BorderBrush="{StaticResource ButtonNormalBorder}"
|
||||
BorderThickness="1">
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="300"></ColumnDefinition>
|
||||
<ColumnDefinition Width="300"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="5,0"
|
||||
FontFamily="Lucida Sans"
|
||||
FontSize="20"
|
||||
FontWeight="Bold"
|
||||
Text="File Uploader" />
|
||||
<TextBlock Margin="5" Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding AuthorFile.SelectedFile}"></TextBlock>
|
||||
<ProgressBar Margin="5" Grid.Row="2" Grid.ColumnSpan="2" Value="{Binding AuthorFile.UploadProgress, Mode=OneWay}" Minimum="0" Maximum="1"></ProgressBar>
|
||||
<Button Margin="5" Grid.Row="3" Grid.Column="0" Command="{Binding AuthorFile.SelectFile, Mode=OneTime}">Select</Button>
|
||||
<Button Margin="5" Grid.Row="3" Grid.Column="1" Command="{Binding AuthorFile.Upload}">Upload</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
</rxui:ReactiveUserControl>
|
@ -47,6 +47,7 @@
|
||||
<WrapPanel>
|
||||
<local:LoginSettingsView x:Name="LoginView" />
|
||||
<local:PerformanceSettingsView x:Name="PerformanceView" />
|
||||
<local:AuthorFilesView x:Name="AuthorFilesView"></local:AuthorFilesView>
|
||||
</WrapPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
@ -173,6 +173,7 @@
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Extensions\DynamicDataExt.cs" />
|
||||
<Compile Include="View Models\Settings\AuthorFilesVM.cs" />
|
||||
<Compile Include="Views\ModListTileView.xaml.cs">
|
||||
<DependentUpon>ModListTileView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -184,6 +185,9 @@
|
||||
<Compile Include="Converters\ConverterRegistration.cs" />
|
||||
<Compile Include="Extensions\IViewForExt.cs" />
|
||||
<Compile Include="View Models\Interfaces\ICpuStatusVM.cs" />
|
||||
<Compile Include="Views\Settings\AuthorFilesView.xaml.cs">
|
||||
<DependentUpon>AuthorFilesView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\LoginItemView.xaml.cs">
|
||||
<DependentUpon>LoginItemView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -308,6 +312,7 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Settings\AuthorFilesView.xaml" />
|
||||
<Page Include="Views\Settings\LoginItemView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@ -543,7 +548,7 @@
|
||||
<Version>1.1.11</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MahApps.Metro">
|
||||
<Version>2.0.0-alpha0660</Version>
|
||||
<Version>1.6.5</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MahApps.Metro.IconPacks">
|
||||
<Version>3.1.0</Version>
|
||||
|
Loading…
Reference in New Issue
Block a user