generated from azures04/Photino-Boilerplate
Big commit
This commit is contained in:
parent
2d7e543163
commit
fe85d2dcc4
@ -7,6 +7,7 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<PublishTrimmed>false</PublishTrimmed>
|
<PublishTrimmed>false</PublishTrimmed>
|
||||||
|
<ApplicationIcon>src/resources/build/icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="PackRenderer" BeforeTargets="DispatchToInnerBuild;BeforeBuild">
|
<Target Name="PackRenderer" BeforeTargets="DispatchToInnerBuild;BeforeBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -18,6 +19,11 @@
|
|||||||
<Exec Command="dotnet "$(BrikPackagerDll)" --action pack --input "$(InputPath)" --output "$(OutputPathFile)" --key 66" />
|
<Exec Command="dotnet "$(BrikPackagerDll)" --action pack --input "$(InputPath)" --output "$(OutputPathFile)" --key 66" />
|
||||||
<Message Importance="high" Text="[] Renderer packed at: $(OutputPathFile)" />
|
<Message Importance="high" Text="[] Renderer packed at: $(OutputPathFile)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="src\resources\build\**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BrikPackager" Version="0.0.1" GeneratePathProperty="true" />
|
<PackageReference Include="BrikPackager" Version="0.0.1" GeneratePathProperty="true" />
|
||||||
<PackageReference Include="Photino.NET" Version="4.0.16" />
|
<PackageReference Include="Photino.NET" Version="4.0.16" />
|
||||||
@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.5.2.0
|
VisualStudioVersion = 17.5.2.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Photino-Boilerplate", "Photino-Boilerplate.csproj", "{5FF73963-D009-62ED-7350-FF17EC625A26}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BrikInstaller", "BrikInstaller.csproj", "{5FF73963-D009-62ED-7350-FF17EC625A26}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
19
src/main/Constants.cs
Normal file
19
src/main/Constants.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json;
|
||||||
|
using BrikInstaller.Utils;
|
||||||
|
|
||||||
|
namespace BrikInstaller;
|
||||||
|
|
||||||
|
public static class Constants {
|
||||||
|
public static readonly JsonSerializerOptions _jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
||||||
|
public static readonly string os = OsHelper.getOperatingSystem();
|
||||||
|
public static readonly string arch = OsHelper.getArchitecture();
|
||||||
|
|
||||||
|
public static readonly string env = "DEV";
|
||||||
|
public static readonly string __dirname = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||||
|
public static readonly string BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
|
||||||
|
public static class URLs {
|
||||||
|
public static readonly string basePoint = "https://brik.azures.fr/products";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,28 +1,29 @@
|
|||||||
using System.Reflection;
|
using Photino.NET;
|
||||||
using System.Text.Json;
|
|
||||||
using BrikPackager;
|
using BrikPackager;
|
||||||
using PhotinoBoilerplate.Utils;
|
using System.Text.Json;
|
||||||
using Photino.NET;
|
using BrikInstaller.Utils;
|
||||||
|
using BrikInstaller.Schemas;
|
||||||
|
using BrikInstaller.Services;
|
||||||
|
|
||||||
namespace PhotinoBoilerplate;
|
namespace BrikInstaller;
|
||||||
|
|
||||||
class Program{
|
class Program{
|
||||||
|
|
||||||
public static readonly JsonSerializerOptions _jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
|
||||||
private static readonly string __dirname = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main(string[] args) {
|
static void Main(string[] args) {
|
||||||
CreateMainWindow().WaitForClose();
|
CreateMainWindow().WaitForClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PhotinoWindow CreateMainWindow() {
|
public static PhotinoWindow CreateMainWindow() {
|
||||||
BrikPackage bpkg = new BrikPackage(Path.Combine(__dirname, "root.dat"), 66);
|
BrikPackage bpkg = new BrikPackage(Path.Combine(Constants.__dirname, "root.dat"), 66);
|
||||||
List<string> entries = bpkg.ListEntries();
|
List<string> entries = bpkg.ListEntries();
|
||||||
|
foreach (string entry in entries) {
|
||||||
|
Console.WriteLine(entry);
|
||||||
|
}
|
||||||
var window = new PhotinoWindow()
|
var window = new PhotinoWindow()
|
||||||
.SetTitle("Photino Boilerplate")
|
.SetTitle("Brik Installer")
|
||||||
.SetUseOsDefaultLocation(false)
|
.SetUseOsDefaultLocation(false)
|
||||||
.SetUseOsDefaultSize(false)
|
.SetUseOsDefaultSize(false)
|
||||||
|
.SetChromeless(true)
|
||||||
.RegisterCustomSchemeHandler("http", (object sender, string scheme, string url, out string contentType) =>{
|
.RegisterCustomSchemeHandler("http", (object sender, string scheme, string url, out string contentType) =>{
|
||||||
Uri uri = new Uri(url);
|
Uri uri = new Uri(url);
|
||||||
switch (uri.Host){
|
switch (uri.Host){
|
||||||
@ -38,41 +39,112 @@ class Program{
|
|||||||
});
|
});
|
||||||
|
|
||||||
window.WindowCreated += (sender, e) => {
|
window.WindowCreated += (sender, e) => {
|
||||||
|
string iconPath = Path.Combine(Constants.BaseDirectory, "src", "resources", "build", "icon.ico");
|
||||||
SetupBridge(window);
|
SetupBridge(window);
|
||||||
WindowHelper.setSize(window, 900, 600);
|
WindowHelper.setSize(window, 465, 290);
|
||||||
|
WindowHelper.RemoveTitleBar(window);
|
||||||
|
WindowHelper.ForceTaskbarIcon(window, iconPath);
|
||||||
window.Center();
|
window.Center();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
window.Load("http://internal/index.html");
|
LoadPage(window, "index.html");
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetupBridge(PhotinoWindow window) {
|
public static void SetupBridge(PhotinoWindow window) {
|
||||||
window.RegisterWebMessageReceivedHandler(async (object? sender, string message) => {
|
window.RegisterWebMessageReceivedHandler(async (object? sender, string message) => {
|
||||||
try {
|
try {
|
||||||
var json = JsonDocument.Parse(message);
|
var json = JsonDocument.Parse(message);
|
||||||
string requestId = json.RootElement.GetProperty("requestId").GetString()!;
|
string requestId = json.RootElement.GetProperty("requestId").GetString()!;
|
||||||
string method = json.RootElement.GetProperty("functionName").GetString()!;
|
string method = json.RootElement.GetProperty("functionName").GetString()!;
|
||||||
var jsonPayload = json.RootElement.GetProperty("payload");
|
var jsonPayload = json.RootElement.GetProperty("payload");
|
||||||
|
|
||||||
|
object? responsePayload = null;
|
||||||
var pw = (PhotinoWindow)sender!;
|
var pw = (PhotinoWindow)sender!;
|
||||||
|
|
||||||
object? payload = null;
|
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case "hello::world":
|
case "network::fetch":
|
||||||
payload = "Hello from C#";
|
responsePayload = await NetworkService.HandleFetchRequest(jsonPayload);
|
||||||
|
break;
|
||||||
|
case "check::requirements":
|
||||||
|
if (jsonPayload.TryGetProperty("soft", out var soft)) {
|
||||||
|
RequirementCheckingResponse requirementChecking = await RequirementsService.CheckRequirementsAsync(pw, soft.GetString()!);
|
||||||
|
if (!requirementChecking.Success) {
|
||||||
|
IPC.sendToRenderer(window, "requirement::failed", null!);
|
||||||
|
} else {
|
||||||
|
IPC.sendToRenderer(window, "requirement::success", null!);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
responsePayload = new { success = false, error = "Soft name missing, wtf?" };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "browser::open":
|
||||||
|
if (jsonPayload.TryGetProperty("url", out var url)) {
|
||||||
|
BashUtils.OpenUrl(url.ToString());
|
||||||
|
} else {
|
||||||
|
responsePayload = new { success = false, error = "Soft name missing, wtf?" };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "installer::elevate":
|
||||||
|
InstallationService.ElevateAndRestart();
|
||||||
|
responsePayload = new { success = true };
|
||||||
|
break;
|
||||||
|
case "installer::testInstallationPath":
|
||||||
|
if (jsonPayload.TryGetProperty("path", out var installPath)) {
|
||||||
|
bool canWrite = InstallationService.CanCreateInPath(installPath.ToString());
|
||||||
|
if (!canWrite) {
|
||||||
|
InstallationService.ElevateAndRestart();
|
||||||
|
responsePayload = new { success = canWrite };
|
||||||
|
} else {
|
||||||
|
responsePayload = new { success = canWrite };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
responsePayload = new { success = false };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "dialog::selectDirectory":
|
||||||
|
string[] selectedFolders = window.ShowOpenFolder();
|
||||||
|
|
||||||
|
if (selectedFolders != null && selectedFolders.Length > 0) {
|
||||||
|
responsePayload = new { success = true, path = selectedFolders[0] };
|
||||||
|
} else {
|
||||||
|
responsePayload = new { success = false };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "installer::defaultInstallPath":
|
||||||
|
if (jsonPayload.TryGetProperty("soft", out var productName)) {
|
||||||
|
string defaultInstallPath = InstallationService.GetDefaultInstallationPath(productName.ToString());
|
||||||
|
responsePayload = new { success = true, path = defaultInstallPath };
|
||||||
|
} else {
|
||||||
|
responsePayload = new { success = false };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "installer::install":
|
||||||
|
if (jsonPayload.TryGetProperty("soft", out var softName) && jsonPayload.TryGetProperty("path", out var softInstallPath)) {
|
||||||
|
try {
|
||||||
|
await GenericFilesService.SyncFilesAsync($"{Constants.URLs.basePoint}/{softName}/{Constants.os}-{Constants.arch}/download/", $"{Constants.URLs.basePoint}/{softName}/{Constants.os}-{Constants.arch}/manifest", softInstallPath.ToString());
|
||||||
|
responsePayload = new { success = true };
|
||||||
|
} catch (Exception) {
|
||||||
|
responsePayload = new { success = false };
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = new { requestId, payload };
|
var finalResponse = new { requestId, payload = responsePayload };
|
||||||
window.SendWebMessage(JsonSerializer.Serialize(response, _jsonOptions));
|
window.SendWebMessage(JsonSerializer.Serialize(finalResponse, Constants._jsonOptions));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Console.WriteLine($"Error stacktrace: {ex.StackTrace}");
|
Console.WriteLine($"Error stacktrace: {ex.StackTrace}");
|
||||||
Console.WriteLine($"Bridge error: {ex.Message}");
|
Console.WriteLine($"Bridge error: {ex.Message}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void LoadPage(PhotinoWindow window, string url) {
|
||||||
|
if (Constants.env == "PROD") {
|
||||||
|
window.Load($"http://internal/{url}");
|
||||||
|
} else {
|
||||||
|
window.Load($"src/resources/renderer/{url}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
70
src/main/helpers/Bash.cs
Normal file
70
src/main/helpers/Bash.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace BrikInstaller.Utils;
|
||||||
|
|
||||||
|
public static class BashUtils {
|
||||||
|
public static string GetCommandOutput(string command) {
|
||||||
|
string shell = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd.exe" : "/bin/bash";
|
||||||
|
string argPrefix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "/c" : "-c";
|
||||||
|
|
||||||
|
string formattedCommand = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? command
|
||||||
|
: $"\"{command.Replace("\"", "\\\"")}\"";
|
||||||
|
|
||||||
|
using var proc = new Process {
|
||||||
|
StartInfo = new ProcessStartInfo {
|
||||||
|
FileName = shell,
|
||||||
|
Arguments = $"{argPrefix} {formattedCommand}",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
StandardOutputEncoding = System.Text.Encoding.UTF8
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
proc.Start();
|
||||||
|
string output = proc.StandardOutput.ReadToEnd();
|
||||||
|
string error = proc.StandardError.ReadToEnd();
|
||||||
|
proc.WaitForExit();
|
||||||
|
|
||||||
|
return string.IsNullOrEmpty(output) ? error : output;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return $"Execution error : {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetBashCommandOutput(string command) {
|
||||||
|
using var proc = new Process {
|
||||||
|
StartInfo = new ProcessStartInfo {
|
||||||
|
FileName = "/bin/bash",
|
||||||
|
Arguments = $"-c \"{command}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
proc.Start();
|
||||||
|
return proc.StandardOutput.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenUrl(string url) {
|
||||||
|
try {
|
||||||
|
Process.Start(url);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||||
|
url = url.Replace("&", "^&");
|
||||||
|
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
|
||||||
|
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
||||||
|
Process.Start("xdg-open", url);
|
||||||
|
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
|
||||||
|
Process.Start("open", url);
|
||||||
|
} else {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/main/helpers/Http.cs
Normal file
51
src/main/helpers/Http.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using BrikInstaller;
|
||||||
|
|
||||||
|
public static class HttpHelper {
|
||||||
|
private static readonly HttpClient Http = new HttpClient();
|
||||||
|
|
||||||
|
public static async Task<HttpResponseMessage> FetchAsync(string url, HttpMethod? method = null, object? body = null, Dictionary<string, string>? headers = null) {
|
||||||
|
Console.WriteLine($"Fetching {url} using {method} method");
|
||||||
|
var request = new HttpRequestMessage(method ?? HttpMethod.Get, url);
|
||||||
|
|
||||||
|
if (headers != null) {
|
||||||
|
foreach (var header in headers) {
|
||||||
|
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body != null) {
|
||||||
|
if (body is HttpContent httpContent) {
|
||||||
|
request.Content = httpContent;
|
||||||
|
} else if (body is string s) {
|
||||||
|
request.Content = new StringContent(s, System.Text.Encoding.UTF8, "application/json");
|
||||||
|
} else {
|
||||||
|
request.Content = JsonContent.Create(body, options: Constants._jsonOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Headers.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||||
|
|
||||||
|
return await Http.SendAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task DownloadFileAsync(string url, string destinationPath) {
|
||||||
|
Console.WriteLine($"Downloading file from {url} to {destinationPath}");
|
||||||
|
string? directory = Path.GetDirectoryName(destinationPath);
|
||||||
|
if (!string.IsNullOrEmpty(directory)) {
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(destinationPath)) {
|
||||||
|
File.Delete(destinationPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var response = await HttpHelper.FetchAsync(url);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
|
||||||
|
using var streamToWriteTo = File.Create(destinationPath);
|
||||||
|
|
||||||
|
await streamToReadFrom.CopyToAsync(streamToWriteTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/helpers/Os.cs
Normal file
31
src/main/helpers/Os.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace BrikInstaller.Utils;
|
||||||
|
|
||||||
|
public static class OsHelper {
|
||||||
|
|
||||||
|
public static string getOperatingSystem() {
|
||||||
|
string os = "unknown";
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||||
|
os = "win";
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
||||||
|
os = "linux";
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
|
||||||
|
os = "macos";
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string getArchitecture() {
|
||||||
|
string arch = RuntimeInformation.OSArchitecture switch {
|
||||||
|
Architecture.X64 => "x64",
|
||||||
|
Architecture.X86 => "x86",
|
||||||
|
Architecture.Arm64 => "arm64",
|
||||||
|
Architecture.Arm => "arm",
|
||||||
|
_ => RuntimeInformation.OSArchitecture.ToString().ToLower()
|
||||||
|
};
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,39 @@
|
|||||||
using Photino.NET;
|
using Photino.NET;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace PhotinoBoilerplate.Utils;
|
namespace BrikInstaller.Utils;
|
||||||
|
|
||||||
public static class WindowHelper {
|
public static class WindowHelper {
|
||||||
|
|
||||||
private const float StandardDpi = 96.0f;
|
private const float StandardDpi = 96.0f;
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType, int cxDesired, int cyDesired, uint fuLoad);
|
||||||
|
|
||||||
|
const int GWL_STYLE = -16;
|
||||||
|
const int WS_CAPTION = 0x00C00000;
|
||||||
|
const int WS_THICKFRAME = 0x00040000;
|
||||||
|
const int WS_MINIMIZEBOX = 0x00020000;
|
||||||
|
const int WS_MAXIMIZEBOX = 0x00010000;
|
||||||
|
const int WS_SYSMENU = 0x00080000;
|
||||||
|
const uint SWP_FRAMECHANGED = 0x0020;
|
||||||
|
const uint SWP_NOMOVE = 0x0002;
|
||||||
|
const uint SWP_NOSIZE = 0x0001;
|
||||||
|
const uint SWP_NOZORDER = 0x0004;
|
||||||
|
const uint WM_SETICON = 0x0080;
|
||||||
|
const IntPtr ICON_SMALL = 0;
|
||||||
|
const IntPtr ICON_BIG = 1;
|
||||||
|
const uint IMAGE_ICON = 1;
|
||||||
|
const uint LR_LOADFROMFILE = 0x00000010;
|
||||||
|
|
||||||
public static Size GetScaledSize(PhotinoWindow window, int logicalWidth, int logicalHeight) {
|
public static Size GetScaledSize(PhotinoWindow window, int logicalWidth, int logicalHeight) {
|
||||||
float currentDpi = window.ScreenDpi > 0 ? window.ScreenDpi : StandardDpi;
|
float currentDpi = window.ScreenDpi > 0 ? window.ScreenDpi : StandardDpi;
|
||||||
@ -22,8 +48,27 @@ public static class WindowHelper {
|
|||||||
public static void setSize(PhotinoWindow window, int width, int height) {
|
public static void setSize(PhotinoWindow window, int width, int height) {
|
||||||
Size targetSize = GetScaledSize(window, width, height);
|
Size targetSize = GetScaledSize(window, width, height);
|
||||||
window
|
window
|
||||||
.SetResizable(true)
|
.SetResizable(false)
|
||||||
.SetSize(targetSize)
|
.SetSize(targetSize)
|
||||||
.SetMinSize(targetSize.Width, targetSize.Height);
|
.SetMinSize(targetSize.Width, targetSize.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RemoveTitleBar(PhotinoWindow window) {
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||||
|
IntPtr hWnd = window.WindowHandle;
|
||||||
|
int style = GetWindowLong(hWnd, GWL_STYLE);
|
||||||
|
style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
|
||||||
|
SetWindowLong(hWnd, GWL_STYLE, style);
|
||||||
|
SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ForceTaskbarIcon(PhotinoWindow window, string iconPath) {
|
||||||
|
IntPtr hWnd = window.WindowHandle;
|
||||||
|
IntPtr hIcon = LoadImage(IntPtr.Zero, iconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
|
||||||
|
if (hIcon != IntPtr.Zero) {
|
||||||
|
SendMessage(hWnd, WM_SETICON, ICON_SMALL, hIcon);
|
||||||
|
SendMessage(hWnd, WM_SETICON, ICON_BIG, hIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
20
src/main/schemas/GenericBrikFiles.cs
Normal file
20
src/main/schemas/GenericBrikFiles.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace BrikInstaller.Schemas;
|
||||||
|
|
||||||
|
public class GenericArtifact {
|
||||||
|
public string Path { get; set; } = string.Empty;
|
||||||
|
public string Sha1 { get; set; } = string.Empty;
|
||||||
|
public long Size { get; set; }
|
||||||
|
public string Url { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BrikFilesIndex {
|
||||||
|
public List<ArtifactEntry> Root { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArtifactEntry {
|
||||||
|
public ArtifactContainer Downloads { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ArtifactContainer {
|
||||||
|
public GenericArtifact Artifact { get; set; } = null!;
|
||||||
|
}
|
||||||
10
src/main/schemas/Product.cs
Normal file
10
src/main/schemas/Product.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace BrikInstaller.Schemas;
|
||||||
|
|
||||||
|
public class ProductRequirement {
|
||||||
|
public string? Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? CheckCommand { get; set; }
|
||||||
|
public string? ExpectedOutputPattern { get; set; }
|
||||||
|
public string? InstallationMode { get; set; }
|
||||||
|
public string? InstallationUrl { get; set; }
|
||||||
|
}
|
||||||
9
src/main/schemas/Requirement.cs
Normal file
9
src/main/schemas/Requirement.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace BrikInstaller.Schemas;
|
||||||
|
|
||||||
|
public class RequirementCheckingResponse {
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string? Error { get; set; }
|
||||||
|
public int? Status { get; set; }
|
||||||
|
|
||||||
|
public bool? hasNoDeps { get; set; }
|
||||||
|
}
|
||||||
56
src/main/services/Files.cs
Normal file
56
src/main/services/Files.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using BrikInstaller.Schemas;
|
||||||
|
|
||||||
|
namespace BrikInstaller.Services;
|
||||||
|
|
||||||
|
public static class GenericFilesService {
|
||||||
|
private static readonly HttpClient _httpClient = new();
|
||||||
|
|
||||||
|
public static async Task SyncFilesAsync(string rootEndpoint, string apiUrl, string destinationDir) {
|
||||||
|
try {
|
||||||
|
var index = await _httpClient.GetFromJsonAsync<BrikFilesIndex>(apiUrl);
|
||||||
|
if (index?.Root == null) return;
|
||||||
|
|
||||||
|
var artifacts = index.Root.Select(r => r.Downloads.Artifact).ToList();
|
||||||
|
await ProcessDownloadsAsync(rootEndpoint, artifacts, destinationDir);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Console.WriteLine($"[Sync Error] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task ProcessDownloadsAsync(string rootEndpoint, List<GenericArtifact> artifacts, string baseDir) {
|
||||||
|
var queue = artifacts.Where(a => !IsFileValid(Path.Combine(baseDir, a.Path), a)).ToList();
|
||||||
|
|
||||||
|
if (queue.Count == 0) return;
|
||||||
|
|
||||||
|
await Parallel.ForEachAsync(queue, new ParallelOptions { MaxDegreeOfParallelism = 4 }, async (artifact, token) => {
|
||||||
|
string localPath = Path.Combine(baseDir, artifact.Path);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await HttpHelper.DownloadFileAsync(rootEndpoint + artifact.Url, localPath);
|
||||||
|
|
||||||
|
if (!IsFileValid(localPath, artifact)) {
|
||||||
|
Console.WriteLine($"[Validation Failed] {artifact.Path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Console.WriteLine($"[Download Error] {artifact.Path}: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsFileValid(string filePath, GenericArtifact expected) {
|
||||||
|
if (!File.Exists(filePath)) return false;
|
||||||
|
|
||||||
|
var info = new FileInfo(filePath);
|
||||||
|
if (info.Length != expected.Size) return false;
|
||||||
|
|
||||||
|
using var stream = File.OpenRead(filePath);
|
||||||
|
byte[] hashBytes = SHA1.HashData(stream);
|
||||||
|
string hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
|
||||||
|
|
||||||
|
return hash == expected.Sha1.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/services/IPC.cs
Normal file
19
src/main/services/IPC.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Photino.NET;
|
||||||
|
|
||||||
|
namespace BrikInstaller.Services;
|
||||||
|
|
||||||
|
public static class IPC {
|
||||||
|
|
||||||
|
public static void sendRequirementCheckConsoleLog(PhotinoWindow window, string log) {
|
||||||
|
sendToRenderer(window, "requirement::log", log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToRenderer(PhotinoWindow window, string requestId, object data) {
|
||||||
|
var logMessage = new {
|
||||||
|
requestId,
|
||||||
|
payload = new { message = data }
|
||||||
|
};
|
||||||
|
window.SendWebMessage(JsonSerializer.Serialize(logMessage, Constants._jsonOptions));
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/main/services/Installation.cs
Normal file
76
src/main/services/Installation.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace BrikInstaller.Services;
|
||||||
|
|
||||||
|
public static class InstallationService {
|
||||||
|
public static bool CanCreateInPath(string folderPath) {
|
||||||
|
if (string.IsNullOrWhiteSpace(folderPath)) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
string fullPath = Path.GetFullPath(folderPath);
|
||||||
|
DirectoryInfo di = new DirectoryInfo(fullPath);
|
||||||
|
|
||||||
|
while (di != null && !di.Exists) {
|
||||||
|
di = di.Parent!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (di == null) return false;
|
||||||
|
|
||||||
|
string testPath = Path.Combine(di.FullName, Guid.NewGuid().ToString());
|
||||||
|
|
||||||
|
Directory.CreateDirectory(testPath);
|
||||||
|
Directory.Delete(testPath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (UnauthorizedAccessException) {
|
||||||
|
return false;
|
||||||
|
} catch (Exception) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ElevateAndRestart() {
|
||||||
|
string exePath = Process.GetCurrentProcess().MainModule!.FileName;
|
||||||
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||||
|
startInfo.FileName = exePath;
|
||||||
|
startInfo.Verb = "runas";
|
||||||
|
startInfo.UseShellExecute = true;
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
||||||
|
startInfo.FileName = "pkexec";
|
||||||
|
startInfo.Arguments = $"\"{exePath}\"";
|
||||||
|
startInfo.UseShellExecute = false;
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
|
||||||
|
startInfo.FileName = "osascript";
|
||||||
|
startInfo.Arguments = $"-e \"do shell script \\\"{exePath}\\\" with administrator privileges\"";
|
||||||
|
startInfo.UseShellExecute = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Process.Start(startInfo);
|
||||||
|
Environment.Exit(0);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Console.WriteLine($"Elevation failed : {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDefaultInstallationPath(string appName) {
|
||||||
|
string final = "";
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||||
|
string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
final = Path.Combine(localAppData, "Programs", appName);
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
||||||
|
string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||||
|
final = Path.Combine(home, ".local", "share", appName.ToLower().Replace(" ", "_"));
|
||||||
|
}
|
||||||
|
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
|
||||||
|
final = $"/Applications/{appName}.app";
|
||||||
|
}
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/main/services/Network.cs
Normal file
30
src/main/services/Network.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using BrikInstaller;
|
||||||
|
|
||||||
|
public static class NetworkService {
|
||||||
|
public static async Task<object> HandleFetchRequest(JsonElement jsonPayload) {
|
||||||
|
try {
|
||||||
|
string url = jsonPayload.GetProperty("url").GetString()!;
|
||||||
|
string httpMethodStr = jsonPayload.TryGetProperty("method", out var m) ? m.GetString()! : "GET";
|
||||||
|
string? body = jsonPayload.TryGetProperty("body", out var b) ? b.GetString() : null;
|
||||||
|
|
||||||
|
Dictionary<string, string>? headers = null;
|
||||||
|
if (jsonPayload.TryGetProperty("headers", out var h)) {
|
||||||
|
headers = JsonSerializer.Deserialize<Dictionary<string, string>>(h.GetRawText(), Constants._jsonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpMethod = new HttpMethod(httpMethodStr.ToUpper());
|
||||||
|
var response = await HttpHelper.FetchAsync(url, httpMethod, body, headers);
|
||||||
|
|
||||||
|
string content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
return new {
|
||||||
|
status = (int)response.StatusCode,
|
||||||
|
success = response.IsSuccessStatusCode,
|
||||||
|
data = content
|
||||||
|
};
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return new { success = false, error = ex.Message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/main/services/Requirements.cs
Normal file
96
src/main/services/Requirements.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using BrikInstaller.Schemas;
|
||||||
|
using BrikInstaller.Utils;
|
||||||
|
using Photino.NET;
|
||||||
|
|
||||||
|
namespace BrikInstaller.Services;
|
||||||
|
|
||||||
|
public static class RequirementsService {
|
||||||
|
public static async Task<RequirementCheckingResponse> CheckRequirementsAsync(PhotinoWindow window, string softName) {
|
||||||
|
try {
|
||||||
|
string requirementsUrl = $"https://brik.azures.fr/products/{softName}/{Constants.os}-{Constants.arch}/requirements";
|
||||||
|
|
||||||
|
var response = await HttpHelper.FetchAsync(requirementsUrl, HttpMethod.Get);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode) {
|
||||||
|
return new RequirementCheckingResponse { Success = false, Status = (int)response.StatusCode };
|
||||||
|
}
|
||||||
|
|
||||||
|
string jsonResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
var requirements = JsonSerializer.Deserialize<List<ProductRequirement>>(jsonResponse, Constants._jsonOptions);
|
||||||
|
|
||||||
|
if (requirements != null) {
|
||||||
|
if (requirements.Count == 0) {
|
||||||
|
return new RequirementCheckingResponse{ Success = true, hasNoDeps = true };
|
||||||
|
}
|
||||||
|
foreach (var element in requirements) {
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement\"></span><b>{element.Name}</b>");
|
||||||
|
int state = await ProcessRequirement(element);
|
||||||
|
switch (state) {
|
||||||
|
case 0:
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_error\"></span> <b>{element.Name}</b>");
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_to_manual_install\"></span><b>{element.Name}</b>");
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_to_manual_install_1\"></span>");
|
||||||
|
return new RequirementCheckingResponse{ Success = false };
|
||||||
|
case 1:
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_error\"></span> <b>{element.Name}</b>");
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_attempt_to_auto_install\"></span><b>{element.Name}</b>");
|
||||||
|
return new RequirementCheckingResponse{ Success = false };
|
||||||
|
case 2:
|
||||||
|
IPC.sendRequirementCheckConsoleLog(window, $"<span data-i18n=\"log_checking_requirement_success\"></span>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new RequirementCheckingResponse{ Success = true };
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Console.WriteLine($"[RequirementsService] Error: {ex.Message}");
|
||||||
|
return new RequirementCheckingResponse{ Success = false, Error = ex.Message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<int> ProcessRequirement(ProductRequirement requirement) {
|
||||||
|
string checkOutput = BashUtils.GetCommandOutput(requirement.CheckCommand!);
|
||||||
|
bool isPresent = Regex.IsMatch(checkOutput, requirement.ExpectedOutputPattern!, RegexOptions.IgnoreCase);
|
||||||
|
if (!isPresent) {
|
||||||
|
bool isAutoinstalled = await RequirementInstallationService.InstallAsync(requirement);
|
||||||
|
return isAutoinstalled == true ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RequirementInstallationService {
|
||||||
|
public static async Task<bool> InstallAsync(ProductRequirement req) {
|
||||||
|
if (string.IsNullOrEmpty(req.InstallationUrl)) return false;
|
||||||
|
|
||||||
|
if (req.InstallationMode == "manual") {
|
||||||
|
BashUtils.OpenUrl(req.InstallationUrl);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.InstallationMode == "auto") {
|
||||||
|
try {
|
||||||
|
var response = await HttpHelper.FetchAsync(req.InstallationUrl);
|
||||||
|
if (!response.IsSuccessStatusCode) return false;
|
||||||
|
|
||||||
|
string extension = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".ps1" : ".sh";
|
||||||
|
string tempPath = Path.Combine(Path.GetTempPath(), $"brik_install_{req.Id}{extension}");
|
||||||
|
|
||||||
|
await File.WriteAllBytesAsync(tempPath, await response.Content.ReadAsByteArrayAsync());
|
||||||
|
|
||||||
|
string cmd = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? $"powershell -ExecutionPolicy Bypass -File \"{tempPath}\""
|
||||||
|
: $"chmod +x \"{tempPath}\" && \"{tempPath}\"";
|
||||||
|
|
||||||
|
BashUtils.GetCommandOutput(cmd);
|
||||||
|
return true;
|
||||||
|
} catch { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/resources/build/icon.ico
Normal file
BIN
src/resources/build/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
BIN
src/resources/build/logo.png
Normal file
BIN
src/resources/build/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
166
src/resources/renderer/assets/css/common.css
Normal file
166
src/resources/renderer/assets/css/common.css
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
user-select: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside > article.frame {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 17px 17px 17px 17px;
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
background-color: #212121;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #dfa615;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: .3s color;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #c99001;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:active {
|
||||||
|
color: #ffb700;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
border: 1px solid #333;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:checked {
|
||||||
|
background-color: #ffb700;
|
||||||
|
border-color: #ffb700;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:checked::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 1px;
|
||||||
|
left: 4px;
|
||||||
|
width: 4px;
|
||||||
|
height: 8px;
|
||||||
|
border: solid white;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: 0px 7px;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.loader {
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.loader > div.full {
|
||||||
|
height: 6px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.loader > div.full > div.loading {
|
||||||
|
height: 6px;
|
||||||
|
width: 50%;
|
||||||
|
transition: 1s width;
|
||||||
|
background-color: #dfa615;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.loader > div.full > div.loading {
|
||||||
|
animation: animateLoadingEffect 0.7s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes animateLoadingEffect {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(200%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fi-es {
|
||||||
|
transform: scale(1.02);
|
||||||
|
transform-origin: center;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fi {
|
||||||
|
backface-visibility: hidden;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #ffffff3d;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: #ffffff5e;
|
||||||
|
}
|
||||||
@ -1,45 +1,151 @@
|
|||||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
|
h1 {
|
||||||
|
font-weight: 550;
|
||||||
* {
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
details > summary {
|
||||||
display: flex;
|
font-size: small;
|
||||||
position: absolute;
|
font-weight: 500px;
|
||||||
top: 0px;
|
}
|
||||||
left: 0px;
|
|
||||||
right: 0px;
|
details {
|
||||||
bottom: 0px;
|
width: 100%;
|
||||||
flex-wrap: wrap;
|
}
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
details.language {
|
||||||
color: #cecece;
|
margin-top: 10px;
|
||||||
background-color: #404551;
|
}
|
||||||
|
|
||||||
|
aside > article.frame > section.author {
|
||||||
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
position: fixed;
|
||||||
font-family: "Poppins", sans-serif;
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside > article.frame > section.author > img {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
margin-right: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside > article.frame > section.author > p {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside > article.frame > section.buttons,
|
||||||
|
aside > article.frame > section.extra_buttons {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
height: 25px;
|
||||||
|
min-width: 50px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 7px 7px 7px 7px;
|
|
||||||
color: #cecece;
|
|
||||||
font-weight: 500;
|
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
border-radius: 5px;
|
color: #ffffff;
|
||||||
background-color: #c8850a;
|
border-radius: 3px;
|
||||||
transition: .3s all;
|
font-weight: 500;
|
||||||
font-family: "Poppins", sans-serif;
|
transition: .3s background-color;
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
background-color: #303030;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
filter: brightness(0.95);
|
background-color: #3a3a3a;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:active {
|
button.primary {
|
||||||
filter: brightness(1.10);
|
background-color: #dfa615;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.primary:hover {
|
||||||
|
background-color: #c99001;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.console {
|
||||||
|
background-color: #1b1b1b;
|
||||||
|
width: 100%;
|
||||||
|
height: 120px;
|
||||||
|
font-size: small;
|
||||||
|
padding: 7px 7px 7px 7px;
|
||||||
|
margin-top: 14px;
|
||||||
|
border-radius: .3s;
|
||||||
|
border-radius: 7px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border: 1px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
article.frame.eula > div.console {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
color: #cecece;
|
||||||
|
background-color: #1b1b1b;
|
||||||
|
}
|
||||||
|
|
||||||
|
article.frame.choosePath > div.installation_path {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 25px;
|
||||||
|
margin-top: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
article.frame.choosePath > div.installation_path > input[type=text] {
|
||||||
|
height: 100%;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
flex: 1;
|
||||||
|
margin-top: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
article.frame.choosePath > div.installation_path > button {
|
||||||
|
height: 100%;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 0;
|
||||||
|
width: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.title {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.title > img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form > div {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form > div > label {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
76
src/resources/renderer/assets/css/select.css
Normal file
76
src/resources/renderer/assets/css/select.css
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
::marker {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
details {
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
width: 200px;
|
||||||
|
height: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #303030;
|
||||||
|
border-radius: 5px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > summary {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
height: 30px;
|
||||||
|
padding-left: 10px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options {
|
||||||
|
width: auto;
|
||||||
|
margin-top: 5px;
|
||||||
|
background-color: #303030;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 90px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options > ul > li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 7px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: .3s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options > ul > li > input[type=radio] {
|
||||||
|
visibility: hidden;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options > ul > li > label {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options > ul > li > label > img,
|
||||||
|
details > summary > img {
|
||||||
|
height: 26px;
|
||||||
|
margin-right: 7px;
|
||||||
|
margin-left: 2px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.fi {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options > ul > li:hover {
|
||||||
|
background-color: #3b3b3b8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > section.options > ul > li:has(input:checked) {
|
||||||
|
background-color: #3b3b3bc9;
|
||||||
|
}
|
||||||
BIN
src/resources/renderer/assets/img/logo.png
Normal file
BIN
src/resources/renderer/assets/img/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
43
src/resources/renderer/assets/js/common.js
Normal file
43
src/resources/renderer/assets/js/common.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
function getPathSeparator() {
|
||||||
|
const isWindows = navigator.platform.toLowerCase() == "win32"
|
||||||
|
return isWindows ? "\\" : "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
const separator = getPathSeparator()
|
||||||
|
|
||||||
|
function toggleLoadingBar() {
|
||||||
|
const loader = document.querySelector("article.frame:not([hidden]) > div.loader")
|
||||||
|
if (loader.hasAttribute("hidden")) {
|
||||||
|
loader.removeAttribute("hidden")
|
||||||
|
} else {
|
||||||
|
loader.setAttribute("hidden", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLoadingBar() {
|
||||||
|
const loader = document.querySelector("article.frame:not([hidden]) > div.loader")
|
||||||
|
if (loader.hasAttribute("hidden")) {
|
||||||
|
loader.removeAttribute("hidden")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideLoadingBar() {
|
||||||
|
const loader = document.querySelector("article.frame:not([hidden]) > div.loader")
|
||||||
|
if (!loader.hasAttribute("hidden")) {
|
||||||
|
loader.setAttribute("hidden", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("wheel", (e) => {
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
}, { passive: false })
|
||||||
|
|
||||||
|
window.onpopstate = () => {
|
||||||
|
window.history.pushState(null, document.title, window.location.href)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
32
src/resources/renderer/assets/js/frames.js
Normal file
32
src/resources/renderer/assets/js/frames.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
const frames = document.querySelectorAll("article.frame")
|
||||||
|
const frameCallbacks = {}
|
||||||
|
|
||||||
|
function showFrame(frameIdentifier) {
|
||||||
|
for (const frame of frames) {
|
||||||
|
frame.setAttribute("hidden", "")
|
||||||
|
if (frame.classList.contains(frameIdentifier)) {
|
||||||
|
frame.removeAttribute("hidden")
|
||||||
|
if (Array.isArray(frameCallbacks[frameIdentifier])) {
|
||||||
|
for (const callback of frameCallbacks[frameIdentifier]) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFrameNavigationButtons() {
|
||||||
|
document.querySelector("article.frame:not([hidden]) > section.buttons").removeAttribute("hidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideFrameNavigationButtons() {
|
||||||
|
document.querySelector("article.frame:not([hidden]) > section.buttons").setAttribute("hidden", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFrameShowed(frameIdentifier, cb) {
|
||||||
|
if (!frameCallbacks[frameIdentifier]) {
|
||||||
|
frameCallbacks[frameIdentifier] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
frameCallbacks[frameIdentifier].push(cb)
|
||||||
|
}
|
||||||
@ -1,4 +1,274 @@
|
|||||||
async function callCSharp() {
|
let products = []
|
||||||
const result = await system.call("hello::world")
|
|
||||||
alert(result)
|
i18next
|
||||||
}
|
.use(i18nextHttpBackend)
|
||||||
|
.init({
|
||||||
|
lng: "fr",
|
||||||
|
fallbackLng: "fr",
|
||||||
|
backend: {
|
||||||
|
loadPath: "./assets/locales/{{lng}}.json",
|
||||||
|
}
|
||||||
|
}, (err, t) => {
|
||||||
|
updatePageContent()
|
||||||
|
})
|
||||||
|
|
||||||
|
function updatePageContent() {
|
||||||
|
document.querySelectorAll("[data-i18n]").forEach(el => {
|
||||||
|
let key = el.getAttribute("data-i18n")
|
||||||
|
|
||||||
|
if (key.startsWith("[")) {
|
||||||
|
const parts = key.split("]")
|
||||||
|
const attr = parts[0].substring(1)
|
||||||
|
const actualKey = parts[1]
|
||||||
|
el.setAttribute(attr, i18next.t(actualKey))
|
||||||
|
} else {
|
||||||
|
el.innerText = i18next.t(key)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function chooseLanguage(dropdownSelector, option) {
|
||||||
|
const select = document.querySelector(`details.${dropdownSelector}`)
|
||||||
|
await choose(dropdownSelector, option)
|
||||||
|
i18next.changeLanguage(select.getAttribute("value"), () => {
|
||||||
|
updatePageContent()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchProducts() {
|
||||||
|
const result = await system.call("network::fetch", {
|
||||||
|
url: "https://brik.azures.fr/products/",
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!result.success) {
|
||||||
|
return console.error("[N::F>(GP)] Error !")
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = JSON.parse(result.data)
|
||||||
|
|
||||||
|
for (const productName of data) {
|
||||||
|
products.push({
|
||||||
|
name: productName,
|
||||||
|
...await fetchInstallerResourcesFor(productName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await makeProductList()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchInstallerResourcesFor(productName) {
|
||||||
|
const result = await system.call("network::fetch", {
|
||||||
|
url: `https://brik.azures.fr/products/${productName}/installerResource`,
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!result.success) {
|
||||||
|
return console.error("[N::F>(GIR)] Error !")
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(result.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeProductList() {
|
||||||
|
const productDropdown = document.querySelector("details.product")
|
||||||
|
const ul = document.createElement("ul")
|
||||||
|
for (const product of products) {
|
||||||
|
const index = products.indexOf(product)
|
||||||
|
const li = document.createElement("li")
|
||||||
|
const radio = document.createElement("input")
|
||||||
|
const label = document.createElement("label")
|
||||||
|
const logo = document.createElement("img")
|
||||||
|
const title = document.createElement("span")
|
||||||
|
|
||||||
|
radio.setAttribute("type", "radio")
|
||||||
|
radio.setAttribute("name", "radio")
|
||||||
|
radio.setAttribute("value", index)
|
||||||
|
radio.setAttribute("id", `box_soft_${index}`)
|
||||||
|
radio.setAttribute("onclick", "choose('product', this)")
|
||||||
|
|
||||||
|
logo.setAttribute("src", product.logo)
|
||||||
|
|
||||||
|
title.innerText = product.name
|
||||||
|
|
||||||
|
label.setAttribute("for", `box_soft_${index}`)
|
||||||
|
label.appendChild(logo)
|
||||||
|
label.appendChild(title)
|
||||||
|
|
||||||
|
li.appendChild(radio)
|
||||||
|
li.appendChild(label)
|
||||||
|
|
||||||
|
ul.appendChild(li)
|
||||||
|
}
|
||||||
|
const options = productDropdown.querySelector("section.options > ul")
|
||||||
|
options.innerHTML = ul.innerHTML
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLogIntoRequirementConsole() {
|
||||||
|
const logsContainer = document.querySelector("article.frame.requirements > div.console")
|
||||||
|
logsContainer.innerHTML = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function putLogIntoRequirementConsole(log) {
|
||||||
|
const logsContainer = document.querySelector("article.frame.requirements > div.console")
|
||||||
|
const code = document.createElement("code")
|
||||||
|
code.innerHTML = log
|
||||||
|
logsContainer.appendChild(code)
|
||||||
|
logsContainer.innerHTML += "<br>"
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFrameExtraButtons() {
|
||||||
|
document.querySelector("article.frame:not([hidden]) > section.extra_buttons").removeAttribute("hidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideFrameExtraButtons() {
|
||||||
|
document.querySelector("article.frame:not([hidden]) > section.extra_buttons").setAttribute("hidden", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedSoftware() {
|
||||||
|
const productDropdown = document.querySelector("details.product")
|
||||||
|
const productIndex = productDropdown.getAttribute("value") + 1
|
||||||
|
const productName = productDropdown.querySelector(`li:nth-of-type(${productIndex})`).children[1].innerText
|
||||||
|
return productName
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterProductArray(productName) {
|
||||||
|
products = products.filter(product => product.name == productName)
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeEula(eula) {
|
||||||
|
const eulaContainer = document.querySelector("article.frame.eula > div.console")
|
||||||
|
const pre = document.createElement("pre")
|
||||||
|
pre.innerText = eula
|
||||||
|
eulaContainer.appendChild(pre)
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearEula() {
|
||||||
|
const eulaContainer = document.querySelector("article.frame.eula > div.console")
|
||||||
|
eulaContainer.innerHTML = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchEula() {
|
||||||
|
const eulaUrl = products[0].eula
|
||||||
|
const result = await system.call("network::fetch", {
|
||||||
|
url: eulaUrl,
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!result.success) {
|
||||||
|
return console.error("[N::F>(GE)] Error !")
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openEULA() {
|
||||||
|
await system.call("browser::open", { url: products[0].eula })
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectDirectory() {
|
||||||
|
const productName = getSelectedSoftware()
|
||||||
|
const result = await system.call("dialog::selectDirectory")
|
||||||
|
if (result.path != null) {
|
||||||
|
if (!result.path.endsWith(productName)) {
|
||||||
|
result.path = result.path + separator + productName
|
||||||
|
}
|
||||||
|
installationPath.setAttribute("value", result.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkInstallationPath(path) {
|
||||||
|
const result = await system.call("installer::testInstallationPath", { path })
|
||||||
|
if (result.success) {
|
||||||
|
showFrameNavigationButtons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFrameShowed("onboarding", () => {
|
||||||
|
const languageDropdown = document.querySelector("details.language")
|
||||||
|
if (languageDropdown.getAttribute("value") == null) {
|
||||||
|
hideFrameNavigationButtons()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onFrameShowed("chooseProduct", () => {
|
||||||
|
const productsDropdown = document.querySelector("details.product")
|
||||||
|
const productIndex = productsDropdown.getAttribute("value")
|
||||||
|
if (productIndex != null) {
|
||||||
|
const product = productsDropdown.querySelector(`li:nth-of-type(${productIndex + 1})`).children[0]
|
||||||
|
choose("product", product)
|
||||||
|
} else {
|
||||||
|
hideFrameNavigationButtons()
|
||||||
|
showFrameExtraButtons()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onFrameShowed("requirements", async () => {
|
||||||
|
const productName = getSelectedSoftware()
|
||||||
|
clearLogIntoRequirementConsole()
|
||||||
|
hideFrameNavigationButtons()
|
||||||
|
hideFrameExtraButtons()
|
||||||
|
showLoadingBar()
|
||||||
|
filterProductArray(productName)
|
||||||
|
await system.call("check::requirements", { soft: productName })
|
||||||
|
})
|
||||||
|
|
||||||
|
onFrameShowed("eula", async () => {
|
||||||
|
clearEula()
|
||||||
|
const eula = await fetchEula()
|
||||||
|
writeEula(eula.data)
|
||||||
|
})
|
||||||
|
|
||||||
|
onFrameShowed("choosePath", async () => {
|
||||||
|
hideFrameNavigationButtons()
|
||||||
|
const result = await system.call("installer::defaultInstallPath", { soft: getSelectedSoftware() })
|
||||||
|
if (result.success) {
|
||||||
|
installationPath.setAttribute("value", result.path)
|
||||||
|
installationPath.onchange()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onFrameShowed("download", async () => {
|
||||||
|
hideFrameExtraButtons()
|
||||||
|
hideFrameNavigationButtons()
|
||||||
|
showLoadingBar()
|
||||||
|
const result = await system.call("installer::install", { soft: getSelectedSoftware(), path: installationPath.getAttribute("value") })
|
||||||
|
hideLoadingBar()
|
||||||
|
if (result.success) {
|
||||||
|
showFrame("end")
|
||||||
|
} else {
|
||||||
|
showFrameExtraButtons()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onSelected("language", () => {
|
||||||
|
showFrameNavigationButtons()
|
||||||
|
})
|
||||||
|
|
||||||
|
onSelected("product", () => {
|
||||||
|
hideFrameExtraButtons()
|
||||||
|
showFrameNavigationButtons()
|
||||||
|
})
|
||||||
|
|
||||||
|
system.result("requirement::log", (data) => {
|
||||||
|
putLogIntoRequirementConsole(data.message)
|
||||||
|
updatePageContent()
|
||||||
|
})
|
||||||
|
|
||||||
|
system.result("requirement::failed", () => {
|
||||||
|
hideLoadingBar()
|
||||||
|
showFrameExtraButtons()
|
||||||
|
})
|
||||||
|
|
||||||
|
system.result("requirement::success", () => {
|
||||||
|
hideLoadingBar()
|
||||||
|
showFrameNavigationButtons()
|
||||||
|
})
|
||||||
|
|
||||||
|
showFrame("onboarding")
|
||||||
|
fetchProducts()
|
||||||
@ -1,14 +1,19 @@
|
|||||||
const system = {
|
const system = {
|
||||||
_pendingRequests: new Map(),
|
_pendingRequests: new Map(),
|
||||||
|
_listeners: new Map(),
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
window.external.receiveMessage(response => {
|
window.external.receiveMessage(response => {
|
||||||
try {
|
try {
|
||||||
const res = JSON.parse(response)
|
const res = JSON.parse(response)
|
||||||
if (res.requestId && this._pendingRequests.has(res.requestId)) {
|
if (res.requestId && this._pendingRequests.has(res.requestId)) {
|
||||||
const { resolve } = this._pendingRequests.get(res.requestId)
|
const { resolve } = this._pendingRequests.get(res.requestId);
|
||||||
this._pendingRequests.delete(res.requestId)
|
this._pendingRequests.delete(res.requestId);
|
||||||
resolve(res.payload)
|
resolve(res.payload);
|
||||||
|
}
|
||||||
|
else if (res.requestId && this._listeners.has(res.requestId)) {
|
||||||
|
const callback = this._listeners.get(res.requestId);
|
||||||
|
callback(res.payload);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Erreur format message :", e)
|
console.error("Erreur format message :", e)
|
||||||
@ -28,7 +33,35 @@ const system = {
|
|||||||
payload: data
|
payload: data
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
result: function(eventName, callback) {
|
||||||
|
this._listeners.set(eventName, callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.external.receiveMessage(message => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(message)
|
||||||
|
|
||||||
|
switch (data.requestId) {
|
||||||
|
case "game::log":
|
||||||
|
const logMessage = data.payload.message
|
||||||
|
if (logMessage != "GAME_CLOSED") {
|
||||||
|
console.log("MC:", logMessage)
|
||||||
|
gamelog.put(logMessage)
|
||||||
|
logsContainer.scrollTop = logsContainer.scrollHeight
|
||||||
|
} else {
|
||||||
|
playButton.removeAttribute("disabled")
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Erreur réception message Photino:", e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
system.init()
|
system.init()
|
||||||
26
src/resources/renderer/assets/js/select.js
Normal file
26
src/resources/renderer/assets/js/select.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const selectCallbacks = {}
|
||||||
|
|
||||||
|
function onSelected(dropdownSelector, cb) {
|
||||||
|
if (!selectCallbacks[dropdownSelector]) {
|
||||||
|
selectCallbacks[dropdownSelector] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
selectCallbacks[dropdownSelector].push(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function choose(dropdownSelector, option) {
|
||||||
|
const select = document.querySelector(`details.${dropdownSelector}`)
|
||||||
|
const title = document.querySelector(`details.${dropdownSelector}>summary`)
|
||||||
|
const value = document.querySelector(`label[for=${option.id}]`)
|
||||||
|
title.innerHTML = value.innerHTML
|
||||||
|
if (select.getAttribute("value") != option.getAttribute("value")) {
|
||||||
|
await sleep(115)
|
||||||
|
}
|
||||||
|
select.setAttribute("value", option.getAttribute("value"))
|
||||||
|
select.removeAttribute("open")
|
||||||
|
if (Array.isArray(selectCallbacks[dropdownSelector])) {
|
||||||
|
for (const callback of selectCallbacks[dropdownSelector]) {
|
||||||
|
callback(option.getAttribute("value"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/arab.json
Normal file
26
src/resources/renderer/assets/locales/arab.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "rtl",
|
||||||
|
"description": "مرحباً بك في مساعد تثبيت Brik",
|
||||||
|
"next": "التالي",
|
||||||
|
"eula": "يرجى قراءة والموافقة على شروط الاستخدام",
|
||||||
|
"exit": "خروج / إنهاء",
|
||||||
|
"retry": "إعادة المحاولة",
|
||||||
|
"accept": "أوافق",
|
||||||
|
"browse": "تصفح",
|
||||||
|
"install": "تثبيت",
|
||||||
|
"previous": "السابق",
|
||||||
|
"downloading": "جاري تحميل ملفات البرنامج",
|
||||||
|
"choose_path": "اختر موقع التثبيت",
|
||||||
|
"create_shortcut": "إنشاء اختصار على سطح المكتب",
|
||||||
|
"launch_after_exit": "تشغيل البرنامج بعد إغلاق المثبت",
|
||||||
|
"installation_path": "اختر مجلد التثبيت",
|
||||||
|
"check_eula_online": "عرض الترخيص في المتصفح",
|
||||||
|
"select_soft_to_install": "اختر البرنامج الذي تود تثبيته",
|
||||||
|
"requirements": "التحقق من المكونات المطلوبة",
|
||||||
|
"log_checking_requirement": "جاري فحص ",
|
||||||
|
"log_checking_requirement_success": "✅ المكون موجود",
|
||||||
|
"log_checking_requirement_error": "❌ مكون ناقص ",
|
||||||
|
"log_checking_requirement_to_manual_install": "يرجى تثبيت المكون الناقص ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "ستفتح صفحة التحميل الآن",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "محاولة التثبيت التلقائي: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/dz.json
Normal file
26
src/resources/renderer/assets/locales/dz.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Merhba bik fi moussa3id installation Brik",
|
||||||
|
"next": "Suivant",
|
||||||
|
"eula": "Y3aychek iqra w wafeq 3la chorout el-isti3mal",
|
||||||
|
"exit": "Khroj / Kmel",
|
||||||
|
"retry": "3awed jareb",
|
||||||
|
"accept": "Nwafeq",
|
||||||
|
"browse": "Parcourir",
|
||||||
|
"install": "Installi",
|
||||||
|
"previous": "Lback / Précédent",
|
||||||
|
"downloading": "Rani n-téléchargi fel-programme",
|
||||||
|
"choose_path": "Khayer win t-installi el-programme",
|
||||||
|
"create_shortcut": "Dir raccourci f-el-bureau",
|
||||||
|
"launch_after_exit": "7el el-programme ki t-oghlaq l-installateur",
|
||||||
|
"installation_path": "Khayer el-dossier ta3 l-installation",
|
||||||
|
"check_eula_online": "Chouf el-contrat f-el-navigateur",
|
||||||
|
"select_soft_to_install": "Khayer el-logiciel li rak hab t-installih",
|
||||||
|
"requirements": "N-verifyiw f-el-7ajet li lazem bech yekhdem",
|
||||||
|
"log_checking_requirement": "N-verifyiw fi ",
|
||||||
|
"log_checking_requirement_success": "✅ Kolchi mriguel",
|
||||||
|
"log_checking_requirement_error": "❌ Kayna 7aja naqsa ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Y3aychek installi el-7aja li naqsa ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Taw tet7al la page ta3 el-téléchargement",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "N-sayiw n-installouha wa7edna: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/en.json
Normal file
26
src/resources/renderer/assets/locales/en.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Welcome to the Brik installation wizard",
|
||||||
|
"next": "Next",
|
||||||
|
"eula": "Please read and accept the terms of use.",
|
||||||
|
"exit": "Quit",
|
||||||
|
"retry": "Retry",
|
||||||
|
"accept": "I accept",
|
||||||
|
"browse": "Browse",
|
||||||
|
"install": "Install",
|
||||||
|
"previous": "Previous",
|
||||||
|
"downloading": "Program files download in progress",
|
||||||
|
"choose_path": "Select the installation location",
|
||||||
|
"create_shortcut": "Create a shortcut on the desktop",
|
||||||
|
"launch_after_exit": "Launch program after closing the installer",
|
||||||
|
"installation_path": "Select the installation location",
|
||||||
|
"check_eula_online": "View the licence in the browser",
|
||||||
|
"select_soft_to_install": "Select the software you wish to install?",
|
||||||
|
"requirements": "Verification of required components",
|
||||||
|
"log_checking_requirement": "Checking ",
|
||||||
|
"log_checking_requirement_success": "✅ Component present ",
|
||||||
|
"log_checking_requirement_error": "❌ Missing component ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Please install the missing component ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "The download page will open",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Attempted automatic installation: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/es.json
Normal file
26
src/resources/renderer/assets/locales/es.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Bienvenido al asistente de instalación de Brik",
|
||||||
|
"next": "Siguiente",
|
||||||
|
"eula": "Por favor, lea y acepte las condiciones de uso.",
|
||||||
|
"exit": "Salir",
|
||||||
|
"retry": "Reintentar",
|
||||||
|
"accept": "Acepto",
|
||||||
|
"browse": "Examinar",
|
||||||
|
"install": "Instalar",
|
||||||
|
"previous": "Anterior",
|
||||||
|
"downloading": "Descarga de archivos del programa en curso",
|
||||||
|
"choose_path": "Seleccione la ubicación de instalación",
|
||||||
|
"create_shortcut": "Crear un acceso directo en el escritorio",
|
||||||
|
"launch_after_exit": "Ejecutar al finalizar",
|
||||||
|
"installation_path": "Seleccione la ruta de instalación",
|
||||||
|
"check_eula_online": "Ver la licencia en el navegador",
|
||||||
|
"select_soft_to_install": "¿Seleccione el software que desea instalar?",
|
||||||
|
"requirements": "Verificación de los componentes requeridos",
|
||||||
|
"log_checking_requirement": "Comprobando ",
|
||||||
|
"log_checking_requirement_success": "✅ Componente presente ",
|
||||||
|
"log_checking_requirement_error": "❌ Componente faltante ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Por favor, instale el componente faltante ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Se abrirá la página de descarga",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Intento de instalación automática: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/et.json
Normal file
26
src/resources/renderer/assets/locales/et.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "ወደ Brik የመጫኛ ረዳት በደህና መጡ",
|
||||||
|
"next": "ቀጣይ",
|
||||||
|
"eula": "እባክዎ የአጠቃቀም ደንቦችን ያንብቡ እና ይስማሙ",
|
||||||
|
"exit": "ውጣ / ጨርስ",
|
||||||
|
"retry": "እንደገና ሞክር",
|
||||||
|
"accept": "እስማማለሁ",
|
||||||
|
"browse": "ፈልግ",
|
||||||
|
"install": "ጫን",
|
||||||
|
"previous": "ተመለስ",
|
||||||
|
"downloading": "የፕሮግራም ፋይሎች በመውረድ ላይ ናቸው",
|
||||||
|
"choose_path": "የመጫኛ ቦታውን ይምረጡ",
|
||||||
|
"create_shortcut": "በዴስክቶፕ ላይ አቋራጭ ፍጠር",
|
||||||
|
"launch_after_exit": "መጫኛው ሲዘጋ ፕሮግራሙን ክፈት",
|
||||||
|
"installation_path": "የመጫኛ ማህደሩን ይምረጡ",
|
||||||
|
"check_eula_online": "ፈቃዱን በአሳሽ ላይ ይመልከቱ",
|
||||||
|
"select_soft_to_install": "ሊጭኑት የሚፈልጉትን ሶፍትዌር ይምረጡ",
|
||||||
|
"requirements": "አስፈላጊ አካላትን በማረጋገጥ ላይ",
|
||||||
|
"log_checking_requirement": "በመፈተሽ ላይ: ",
|
||||||
|
"log_checking_requirement_success": "✅ አካሉ ተገኝቷል",
|
||||||
|
"log_checking_requirement_error": "❌ የጎደለ አካል አለ",
|
||||||
|
"log_checking_requirement_to_manual_install": "እባክዎ የጎደለውን አካል ይጫኑ: ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "የማውረጃው ገጽ አሁን ይከፈታል",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "ራሱን በራሱ ለመጫን እየሞከረ ነው: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/fr.json
Normal file
26
src/resources/renderer/assets/locales/fr.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Bienvenue dans l'assistant d'installation Brik",
|
||||||
|
"next": "Suivant",
|
||||||
|
"eula": "Veuillez lire et accepter les conditions d'utilisation",
|
||||||
|
"exit": "Quitter / Terminer",
|
||||||
|
"retry": "Réessayer",
|
||||||
|
"accept": "J'accepte",
|
||||||
|
"install": "Installer",
|
||||||
|
"browse": "Parcourir",
|
||||||
|
"previous": "Précédent",
|
||||||
|
"downloading": "Téléchargement du programme en cours",
|
||||||
|
"choose_path": "Choisissez l'emplacement d'installation",
|
||||||
|
"create_shortcut": "Créer un raccourci sur le bureau",
|
||||||
|
"launch_after_exit": "Lancer le programme après la fermeture de l'installateur",
|
||||||
|
"installation_path": "Sélectionnez le dossier d'installation",
|
||||||
|
"check_eula_online": "Consulter la licence dans le navigateur",
|
||||||
|
"select_soft_to_install": "Choisissez le logiciel que vous souhaitez installer",
|
||||||
|
"requirements": "Vérification des composants requis",
|
||||||
|
"log_checking_requirement": "Vérification de ",
|
||||||
|
"log_checking_requirement_success": "✅ Composant présent",
|
||||||
|
"log_checking_requirement_error": "❌ Composant manquant ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Veuillez installer le composant manquant ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "La page de téléchargement va s'ouvrir",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Tentative d'installation automatique : "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/it.json
Normal file
26
src/resources/renderer/assets/locales/it.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Benvenuto nella procedura guidata di installazione di Brik",
|
||||||
|
"next": "Successivo",
|
||||||
|
"eula": "Leggi e accetta i termini di utilizzo.",
|
||||||
|
"exit": "Esci",
|
||||||
|
"retry": "Retry",
|
||||||
|
"accept": "Riprova",
|
||||||
|
"browse": "Sfoglia",
|
||||||
|
"install": "Installare",
|
||||||
|
"previous": "Precedente",
|
||||||
|
"downloading": "Download dei file di programma in corso",
|
||||||
|
"choose_path": "Selezionare la posizione di installazione",
|
||||||
|
"create_shortcut": "Creare un collegamento sul desktop",
|
||||||
|
"launch_after_exit": "Apri dopo l'installazione",
|
||||||
|
"installation_path": "Selezionare la posizione di installazione",
|
||||||
|
"check_eula_online": "Visualizza la licenza nel browser",
|
||||||
|
"select_soft_to_install": "Selezionare il software che si desidera installare?",
|
||||||
|
"requirements": "Verifica dei componenti richiesti",
|
||||||
|
"log_checking_requirement": "Controllo ",
|
||||||
|
"log_checking_requirement_success": "✅ Componente presente ",
|
||||||
|
"log_checking_requirement_error": "❌ Componente mancante ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Si prega di installare il componente mancante ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Si aprirà la pagina di download",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Tentativo di installazione automatica: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/jp.json
Normal file
26
src/resources/renderer/assets/locales/jp.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Brik インストールウィザードへようこそ",
|
||||||
|
"next": "次へ",
|
||||||
|
"eula": "利用規約を読み、同意してください。",
|
||||||
|
"exit": "終了",
|
||||||
|
"retry": "再試行",
|
||||||
|
"accept": "同意する",
|
||||||
|
"browse": "参照",
|
||||||
|
"install": "インストール",
|
||||||
|
"previous": "戻る",
|
||||||
|
"downloading": "プログラムファイルをダウンロード中...",
|
||||||
|
"choose_path": "インストール先を選択してください",
|
||||||
|
"create_shortcut": "デスクトップにショートカットを作成する",
|
||||||
|
"launch_after_exit": "終了後にプログラムを起動する",
|
||||||
|
"installation_path": "インストール先のフォルダを選択",
|
||||||
|
"check_eula_online": "ブラウザでライセンスを確認する",
|
||||||
|
"select_soft_to_install": "インストールするソフトウェアを選択してください",
|
||||||
|
"requirements": "必須コンポーネントの確認中",
|
||||||
|
"log_checking_requirement": "確認中: ",
|
||||||
|
"log_checking_requirement_success": "✅ コンポーネントが見つかりました",
|
||||||
|
"log_checking_requirement_error": "❌ コンポーネントが不足しています",
|
||||||
|
"log_checking_requirement_to_manual_install": "不足しているコンポーネントをインストールしてください: ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "ダウンロードページを開きます",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "自動インストールを試行中: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/ma.json
Normal file
26
src/resources/renderer/assets/locales/ma.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Merhba bik f mosa3id tatbit Brik",
|
||||||
|
"next": "Tali",
|
||||||
|
"eula": "3afak iqra w wafeq 3la chourout l-istis3mal",
|
||||||
|
"exit": "Khrouj / Salina",
|
||||||
|
"retry": "3awed jereb",
|
||||||
|
"accept": "Kanwafeq",
|
||||||
|
"browse": "Parcourir",
|
||||||
|
"install": "Installi",
|
||||||
|
"previous": "L-pari li fat",
|
||||||
|
"downloading": "Jarri l-tahmil dyal l-programme",
|
||||||
|
"choose_path": "Khtar fin t-installi l-programme",
|
||||||
|
"create_shortcut": "Dir raccourci f l-bureau",
|
||||||
|
"launch_after_exit": "Khdem l-programme melli tsed l-installateur",
|
||||||
|
"installation_path": "Khtar l-dossier dyal l-installation",
|
||||||
|
"check_eula_online": "Chouf l-license f l-navigateur",
|
||||||
|
"select_soft_to_install": "Khtar l-logiciel li bghiti t-installi",
|
||||||
|
"requirements": "Kan-verifiw l-7ajat li daroria bach ykhdem",
|
||||||
|
"log_checking_requirement": "Verificassion dyal ",
|
||||||
|
"log_checking_requirement_success": "✅ Kolchi houwa hadak",
|
||||||
|
"log_checking_requirement_error": "❌ Kayna 7aja naqsa ",
|
||||||
|
"log_checking_requirement_to_manual_install": "3afak installi had l-7aja li naqsa ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Ghat-t-fte7 l-pari dyal l-tahmil",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Ghan-jerrbo n-installiwha rousna: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/ng.json
Normal file
26
src/resources/renderer/assets/locales/ng.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Ẹ kú àbọ̀ sí abẹ́yọrí ìfilọ́lẹ̀ Brik",
|
||||||
|
"next": "Tẹ̀síwájú",
|
||||||
|
"eula": "Jọ̀wọ́ ka kí o sì gbà fún àwọn òfin ì lò.",
|
||||||
|
"exit": "Jáde / Parí",
|
||||||
|
"retry": "Ìdánwò lẹ́ẹ̀kan sí i",
|
||||||
|
"accept": "Mo gbà",
|
||||||
|
"browse": "Wá kiri",
|
||||||
|
"install": "Fi bẹ̀rẹ̀",
|
||||||
|
"previous": "Padà sẹ́yìn",
|
||||||
|
"downloading": "Ìgbàsílẹ̀ àwọn fáìlì ètò ń lọ lọ́wọ́...",
|
||||||
|
"choose_path": "Yan ibi tí o fẹ́ fi ètò sí",
|
||||||
|
"create_shortcut": "Ṣẹ̀dá ọ̀nà ìkékúrú sórí ojú iṣẹ́ (desktop)",
|
||||||
|
"launch_after_exit": "Ṣí ètò lẹ́yìn tí o bá ti ti olùfilọ́lẹ̀",
|
||||||
|
"installation_path": "Yan ibi tí ètò yóò wà",
|
||||||
|
"check_eula_online": "Wo ìwé àṣẹ nínú ẹ̀rọ ìṣíwò (browser)",
|
||||||
|
"select_soft_to_install": "Yan ètò (software) tí o fẹ́ fi bẹ̀rẹ̀",
|
||||||
|
"requirements": "Ìmúdájú àwọn nǹkan tí ó ṣe dandan",
|
||||||
|
"log_checking_requirement": "Ìyẹ̀wò lọ́wọ́: ",
|
||||||
|
"log_checking_requirement_success": "✅ Ohun èlò ti wà",
|
||||||
|
"log_checking_requirement_error": "❌ Ohun èlò kan dín bù ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Jọ̀wọ́ fi ohun èlò tí ó dín bù bẹ̀rẹ̀ ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Ojú-ewé ìgbàsílẹ̀ yóò ṣí nísìnyí",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Ìgbìnyànjú láti fi bẹ̀rẹ̀ fúnrawá: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/ru.json
Normal file
26
src/resources/renderer/assets/locales/ru.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Добро пожаловать в мастер установки Brik",
|
||||||
|
"next": "Далее",
|
||||||
|
"eula": "Пожалуйста, прочтите и примите условия использования",
|
||||||
|
"exit": "Выход",
|
||||||
|
"retry": "Повторить",
|
||||||
|
"accept": "Я принимаю",
|
||||||
|
"browse": "Обзор",
|
||||||
|
"install": "Установить",
|
||||||
|
"previous": "Назад",
|
||||||
|
"downloading": "Загрузка файлов программы...",
|
||||||
|
"choose_path": "Выберите путь установки",
|
||||||
|
"create_shortcut": "Создать ярлык на рабочем столе",
|
||||||
|
"launch_after_exit": "Запустить программу после завершения",
|
||||||
|
"installation_path": "Выберите папку для установки",
|
||||||
|
"check_eula_online": "Посмотреть лицензию в браузере",
|
||||||
|
"select_soft_to_install": "Выберите компоненты для установки",
|
||||||
|
"requirements": "Проверка системных требований",
|
||||||
|
"log_checking_requirement": "Проверка: ",
|
||||||
|
"log_checking_requirement_success": "✅ Компонент найден",
|
||||||
|
"log_checking_requirement_error": "❌ Компонент отсутствует",
|
||||||
|
"log_checking_requirement_to_manual_install": "Пожалуйста, установите недостающий компонент: ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Сейчас откроется страница загрузки",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Попытка автоматической установки: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/sn.json
Normal file
26
src/resources/renderer/assets/locales/sn.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Dalal jàmm ci sarsaralub instalasiyoŋu Brik",
|
||||||
|
"next": "Kanami",
|
||||||
|
"eula": "Nanga gëstu te nangu sàrti jëfandiku gi",
|
||||||
|
"exit": "Génn / Pare",
|
||||||
|
"retry": "Baraat ko",
|
||||||
|
"accept": "Nangu naa",
|
||||||
|
"browse": "Seet",
|
||||||
|
"install": "Instale",
|
||||||
|
"previous": "Ginnaaw",
|
||||||
|
"downloading": "Yebum kàggi porogaraam bi mu ngi nekk ci yoon",
|
||||||
|
"choose_path": "Tànnal bërëb bi ñuy instale porogaraam bi",
|
||||||
|
"create_shortcut": "Sudar ab ràccu ci tablo bi",
|
||||||
|
"launch_after_exit": "Ubi porogaraam bi su instalatër bi tëjoo",
|
||||||
|
"installation_path": "Tànnal kàggub instalasiyoŋ bi",
|
||||||
|
"check_eula_online": "Gëstu sàrt yi ci internet",
|
||||||
|
"select_soft_to_install": "Tànnal porogaraam bi nga bëggë instale",
|
||||||
|
"requirements": "Xayma kàggi yi ñu laaj ngir mu liggéey",
|
||||||
|
"log_checking_requirement": "Xayma bu ",
|
||||||
|
"log_checking_requirement_success": "✅ Lépp mu ngi dox",
|
||||||
|
"log_checking_requirement_error": "❌ Am na kàggi lu manke ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Nanga instale kàggi li manke ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Xëtub yeb bi dina ubeeku léegi",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Njeemeb instalasiyoŋ bu boppam: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/tamazight.json
Normal file
26
src/resources/renderer/assets/locales/tamazight.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Ansuf yiswen ɣer imawan n ussebded n Brik",
|
||||||
|
"next": "Afus d-iteddun",
|
||||||
|
"eula": "Ɛafak ɣer ukan tqebleḍ timentilin n usemres",
|
||||||
|
"exit": "Ffeɣ / Kmel",
|
||||||
|
"retry": "Ɛawed jareb",
|
||||||
|
"accept": "Qebleɣ",
|
||||||
|
"browse": "Snubbjet",
|
||||||
|
"install": "Ssebded",
|
||||||
|
"previous": "Amezwaru",
|
||||||
|
"downloading": "Agmar n yifuyla n uselkim",
|
||||||
|
"choose_path": "Fren amkan n ussebded",
|
||||||
|
"create_shortcut": "Snerni rracoursi di ttabla",
|
||||||
|
"launch_after_exit": "Ssekker aselkim madi tmedleḍ amezen n ussebded",
|
||||||
|
"installation_path": "Fren akaram n ussebded",
|
||||||
|
"check_eula_online": "Ẓer tasiregt di ttanfult",
|
||||||
|
"select_soft_to_install": "Fren aselkim i tebɣid ad tsebdeded",
|
||||||
|
"requirements": "Aselken n yiferdisen i d-ittwasutren",
|
||||||
|
"log_checking_requirement": "Aselken n ",
|
||||||
|
"log_checking_requirement_success": "✅ Kulci yella",
|
||||||
|
"log_checking_requirement_error": "❌ Yella wayen i khussen ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Ɛafak ssebded ayen i khussen ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Tasaft n ugmar a d-teldi tura",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Armud n ussebded n yiman-is: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/tn.json
Normal file
26
src/resources/renderer/assets/locales/tn.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Marhba bik fi moussa3id installation Brik",
|
||||||
|
"next": "Tali",
|
||||||
|
"eula": "Y3aychek iqra w wafeq 3ala chourout el-istis3mal",
|
||||||
|
"exit": "Okhrjou / Kmal",
|
||||||
|
"retry": "3awed jareb",
|
||||||
|
"accept": "Nwafeq",
|
||||||
|
"browse": "Lawwej",
|
||||||
|
"install": "Installi",
|
||||||
|
"previous": "Litali",
|
||||||
|
"downloading": "Qa3ed ncharji fel-programme",
|
||||||
|
"choose_path": "Ekhtar win tseb el-programme",
|
||||||
|
"create_shortcut": "A3mel raccourci 3al-bureau",
|
||||||
|
"launch_after_exit": "7el el-programme ki tsekker l-installateur",
|
||||||
|
"installation_path": "Ekter el-dossier mta3 l-installation",
|
||||||
|
"check_eula_online": "Chouf el-license fel-navigateur",
|
||||||
|
"select_soft_to_install": "Ekhtar el-logiciel elli t7eb tsebbo",
|
||||||
|
"requirements": "Nthabtou fel-7ajet elli lezmin bech yekhdem",
|
||||||
|
"log_checking_requirement": "Nthabtou fi ",
|
||||||
|
"log_checking_requirement_success": "✅ Kol chay mriguel",
|
||||||
|
"log_checking_requirement_error": "❌ Famma 7aja naqsa ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Y3aychek sab el-7aja elli naqsa ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Taw tet7al saf7et el-telechargement",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Taw njarbou nsebboha wa7edna: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/tz.json
Normal file
26
src/resources/renderer/assets/locales/tz.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Karibu kwenye programu ya usakinishaji ya Brik",
|
||||||
|
"next": "Endelea",
|
||||||
|
"eula": "Tafadhali soma na ukubali masharti ya matumizi",
|
||||||
|
"exit": "Ondoka / Maliza",
|
||||||
|
"retry": "Jaribu tena",
|
||||||
|
"accept": "Ninakubali",
|
||||||
|
"browse": "Vinjari",
|
||||||
|
"install": "Sakinisha",
|
||||||
|
"previous": "Rudi nyuma",
|
||||||
|
"downloading": "Upakuaji wa faili za programu unaendelea",
|
||||||
|
"choose_path": "Chagua mahali pa kusakinisha",
|
||||||
|
"create_shortcut": "Weka njia ya mkato kwenye desktop",
|
||||||
|
"launch_after_exit": "Fungua programu baada ya kufunga kisakinishi",
|
||||||
|
"installation_path": "Chagua folda ya usakinishaji",
|
||||||
|
"check_eula_online": "Angalia leseni kwenye kivinjari",
|
||||||
|
"select_soft_to_install": "Chagua programu unayotaka kusakinisha",
|
||||||
|
"requirements": "Uhakiki wa vipengele vinavyohitajika",
|
||||||
|
"log_checking_requirement": "Inakagua ",
|
||||||
|
"log_checking_requirement_success": "✅ Kipengele kipo",
|
||||||
|
"log_checking_requirement_error": "❌ Kipengele kinakosekana ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Tafadhali sakinisha kipengele kinachokosekana ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Ukurasa wa upakuaji utafunguka",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Jaribio la usakinishaji wa kiotomatiki: "
|
||||||
|
}
|
||||||
26
src/resources/renderer/assets/locales/za.json
Normal file
26
src/resources/renderer/assets/locales/za.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"layout_direction": "ltr",
|
||||||
|
"description": "Siyakwamukela kusisizi sokufaka se-Brik",
|
||||||
|
"next": "Okulandelayo",
|
||||||
|
"eula": "Sicela ufunde futhi ulande imigomo yokusetshenziswa",
|
||||||
|
"exit": "Phuma / Qeda",
|
||||||
|
"retry": "Zama futhi",
|
||||||
|
"accept": "Ngiyavuma",
|
||||||
|
"browse": "Bhekisisa",
|
||||||
|
"install": "Faka",
|
||||||
|
"previous": "Okwedlule",
|
||||||
|
"downloading": "Kulandwa amafayela ohlelo...",
|
||||||
|
"choose_path": "Khetha lapho uzofaka khona uhlelo",
|
||||||
|
"create_shortcut": "Yenza isinqamuleli kudeskithophu",
|
||||||
|
"launch_after_exit": "Vula uhlelo ngemuva kokuvala isifaki",
|
||||||
|
"installation_path": "Khetha ifolda yokufaka",
|
||||||
|
"check_eula_online": "Buka ilayisensi kusiphequluli",
|
||||||
|
"select_soft_to_install": "Khetha isofthiwe ofuna ukuyifaka",
|
||||||
|
"requirements": "Ukuhlola izinto ezidingekayo",
|
||||||
|
"log_checking_requirement": "Kuhlolwa ",
|
||||||
|
"log_checking_requirement_success": "✅ Konke kulungile",
|
||||||
|
"log_checking_requirement_error": "❌ Kukhona okushortayo ",
|
||||||
|
"log_checking_requirement_to_manual_install": "Sicela ufake lokhu okushortayo ",
|
||||||
|
"log_checking_requirement_to_manual_install_1": "Ikhasi lokulanda lizovuleka manje",
|
||||||
|
"log_checking_requirement_attempt_to_auto_install": "Kuzanywa ukufaka ngokuzenzakalelayo: "
|
||||||
|
}
|
||||||
@ -3,21 +3,292 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="./assets/css/common.css">
|
||||||
|
<link rel="stylesheet" href="./assets/css/select.css">
|
||||||
<link rel="stylesheet" href="./assets/css/index.css">
|
<link rel="stylesheet" href="./assets/css/index.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.3.2/css/flag-icons.min.css" crossorigin="anonymous"/>
|
||||||
<title></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<h2>
|
<aside>
|
||||||
Bienvenue dans Photino
|
<article class="frame onboarding">
|
||||||
</h2>
|
<div class="title">
|
||||||
<button onclick="callCSharp()">
|
<img src="./assets/img/logo.png" alt="">
|
||||||
Appellez une fonction C#
|
<h1>
|
||||||
</button>
|
Brik Installer
|
||||||
</main>
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p data-i18n="description">
|
||||||
|
</p>
|
||||||
|
<details class="language">
|
||||||
|
<summary>
|
||||||
|
Sélectionner une langue
|
||||||
|
</summary>
|
||||||
|
<section class="options">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="fr" name="radio" id="box_lang_fr" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_fr">
|
||||||
|
<span class="fi fi-fr"></span>
|
||||||
|
Français
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="tn" name="radio" id="box_lang_tn" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_tn">
|
||||||
|
<span class="fi fi-tn"></span>
|
||||||
|
Darja Tounsi
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="dz" name="radio" id="box_lang_dz" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_dz">
|
||||||
|
<span class="fi fi-dz"></span>
|
||||||
|
Dziria
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="ma" name="radio" id="box_lang_ma" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_ma">
|
||||||
|
<span class="fi fi-ma"></span>
|
||||||
|
Darija Maghribia
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="tamazight" name="radio" id="box_lang_tamazight" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_tamazight">
|
||||||
|
ⵣ Tamazight (Tifinagh)
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="it" name="radio" id="box_lang_it" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_it">
|
||||||
|
<span class="fi fi-it"></span>
|
||||||
|
Italiano
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="en" name="radio" id="box_lang_en" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_en">
|
||||||
|
<span class="fi fi-gb"></span>
|
||||||
|
English
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="es" name="radio" id="box_lang_es" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_es">
|
||||||
|
<span class="fi fi-es"></span>
|
||||||
|
Espanol
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="ru" name="radio" id="box_lang_ru" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_ru">
|
||||||
|
<span class="fi fi-ru"></span>
|
||||||
|
Русский
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="jp" name="radio" id="box_lang_jp" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_jp">
|
||||||
|
<span class="fi fi-jp"></span>
|
||||||
|
日本語
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="arab" name="radio" id="box_lang_arab" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_arab">
|
||||||
|
<span class="fi fi-arab"></span>
|
||||||
|
ع
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="tz" name="radio" id="box_lang_tz" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_tz">
|
||||||
|
<span class="fi fi-tz"></span>
|
||||||
|
Swahili
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="sn" name="radio" id="box_lang_sn" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_sn">
|
||||||
|
<span class="fi fi-sn"></span>
|
||||||
|
Wolof
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="ng" name="radio" id="box_lang_ng" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_ng">
|
||||||
|
<span class="fi fi-ng"></span>
|
||||||
|
Yoruba
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="et" name="radio" id="box_lang_et" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_et">
|
||||||
|
<span class="fi fi-et"></span>
|
||||||
|
Amharique
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="radio" value="za" name="radio" id="box_lang_za" onclick="chooseLanguage('language', this)"/>
|
||||||
|
<label for="box_lang_za">
|
||||||
|
<span class="fi fi-za"></span>
|
||||||
|
Zulu
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</details>
|
||||||
|
<section class="author">
|
||||||
|
<img src="https://github.com/azures04.png?size=1024" alt="">
|
||||||
|
<p>
|
||||||
|
azures04
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="next" onclick="showFrame('chooseProduct')">
|
||||||
|
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
<article class="frame chooseProduct">
|
||||||
|
<div class="title">
|
||||||
|
<img src="./assets/img/logo.png" alt="">
|
||||||
|
<h1>
|
||||||
|
Brik Installer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<details class="product">
|
||||||
|
<summary data-i18n="select_soft_to_install">
|
||||||
|
|
||||||
|
</summary>
|
||||||
|
<section class="options">
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</details>
|
||||||
|
<section class="extra_buttons" hidden>
|
||||||
|
<button data-i18n="previous" onclick="showFrame('onboarding')"></button>
|
||||||
|
</section>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="next" onclick="showFrame('requirements')"></button>
|
||||||
|
<button data-i18n="previous" onclick="showFrame('onboarding')"></button>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
<article class="frame requirements">
|
||||||
|
<div class="title">
|
||||||
|
<img src="./assets/img/logo.png" alt="">
|
||||||
|
<h1>
|
||||||
|
Brik Installer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p data-i18n="requirements"></p>
|
||||||
|
<div class="console">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="next" onclick="showFrame('eula')"></button>
|
||||||
|
<button data-i18n="previous" onclick="showFrame('chooseProduct')"></button>
|
||||||
|
</section>
|
||||||
|
<section class="extra_buttons" hidden>
|
||||||
|
<button class="primary" data-i18n="retry" onclick="showFrame('requirements')"></button>
|
||||||
|
</section>
|
||||||
|
<div class="loader" hidden>
|
||||||
|
<div class="full">
|
||||||
|
<div class="loading">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="frame eula">
|
||||||
|
<div class="title">
|
||||||
|
<img src="./assets/img/logo.png" alt="">
|
||||||
|
<h1>
|
||||||
|
Brik Installer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p data-i18n="eula"></p>
|
||||||
|
<div class="console">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a onclick="openEULA()" data-i18n="check_eula_online"></a>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="accept" onclick="showFrame('choosePath')"></button>
|
||||||
|
<button data-i18n="previous" onclick="showFrame('requirements')"></button>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
<article class="frame choosePath">
|
||||||
|
<div class="title">
|
||||||
|
<img src="./assets/img/logo.png" alt="">
|
||||||
|
<h1>
|
||||||
|
Brik Installer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p data-i18n="choose_path"></p>
|
||||||
|
<div class="installation_path">
|
||||||
|
<input type="text" id="installationPath" onchange="checkInstallationPath(this.value)" data-i18n="[placeholder]installation_path">
|
||||||
|
<button onclick="selectDirectory()" data-i18n="browse"></button>
|
||||||
|
</div>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="install" onclick="showFrame('download')"></button>
|
||||||
|
<button data-i18n="previous" onclick="showFrame('eula')"></button>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
<article class="frame download">
|
||||||
|
<div class="title">
|
||||||
|
<img src="./assets/img/logo.png" alt="">
|
||||||
|
<h1>
|
||||||
|
Brik Installer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p data-i18n="downloading"></p>
|
||||||
|
<div class="loader" hidden>
|
||||||
|
<div class="full">
|
||||||
|
<div class="loading">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<section class="extra_buttons">
|
||||||
|
<button class="primary" data-i18n="retry" onclick="showFrame('download')"></button>
|
||||||
|
<button data-i18n="previous" onclick="showFrame('choosePath')"></button>
|
||||||
|
</section>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="exit" onclick="window.close()"></button>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
<article class="frame end">
|
||||||
|
<div class="title">
|
||||||
|
<img src="./assets/img/logo.png" alt="">
|
||||||
|
<h1>
|
||||||
|
Brik Installer
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<form>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" name="createShortcut" id="createShortcut" value="createShortcut" checked>
|
||||||
|
<label for="createShortcut" data-i18n="create_shortcut">createShortcut</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" name="launchAfterExit" id="launchAfterExit" value="launchAfterExit">
|
||||||
|
<label for="launchAfterExit" data-i18n="launch_after_exit"></label>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<section class="buttons">
|
||||||
|
<button class="primary" data-i18n="exit" onclick="window.close()"></button>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</aside>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/i18next@25.8.4/dist/umd/i18next.min.js" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://unpkg.com/i18next-http-backend@2.5.2/i18nextHttpBackend.min.js" crossorigin="anonymous"></script>
|
||||||
<script src="./assets/js/ipc.js"></script>
|
<script src="./assets/js/ipc.js"></script>
|
||||||
|
<script src="./assets/js/common.js"></script>
|
||||||
|
<script src="./assets/js/select.js"></script>
|
||||||
|
<script src="./assets/js/frames.js"></script>
|
||||||
<script src="./assets/js/index.js"></script>
|
<script src="./assets/js/index.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user