This commit is contained in:
Michael Green
2024-12-27 08:07:10 +11:00
parent ffd4dcbb33
commit ae41fae54f
16 changed files with 347 additions and 63 deletions

View File

@@ -4,7 +4,7 @@ FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm
RUN apt-get update
# download and unzip EmulatorJS from CDN
RUN apt-get install -y p7zip-full
RUN apt-get install -y p7zip-full default-jdk nodejs wget
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
RUN wget https://cdn.emulatorjs.org/releases/4.1.1.7z
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.1.1.7z

View File

@@ -1,27 +1,25 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
{
"name": "C# (.NET)",
"name": "Gaseous C# (.NET)",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
//"image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm",
"dockerComposeFile": "docker-compose.yml",
"service": "development",
"workspaceFolder": "/workspace",
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [5198],
"forwardPorts": [
5198
],
"portsAttributes": {
"5198": {
"protocol": "http"
}
"5198": {
"protocol": "http"
}
},
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "dotnet restore",
// Configure tool-specific properties.
"customizations": {
"vscode": {
@@ -38,11 +36,11 @@
"ms-dotnettools.vscodeintellicode-csharp",
"Zignd.html-css-class-completion",
"PWABuilder.pwa-studio",
"ms-azuretools.vscode-docker"
"ms-azuretools.vscode-docker",
"SonarSource.sonarlint-vscode"
]
}
}
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}

View File

@@ -337,11 +337,23 @@ namespace gaseous_server.Classes
// only IGDB metadata is supported
if (metadataResult.Source == HasheousClient.Models.MetadataSources.IGDB)
{
if (metadataResult.Id.Length > 0)
if (metadataResult.ImmutableId.Length > 0)
{
// use immutable id
Platform hasheousPlatform = Platforms.GetPlatform(long.Parse(metadataResult.ImmutableId));
signature.MetadataSources.AddPlatform((long)hasheousPlatform.Id, hasheousPlatform.Name, metadataResult.Source);
}
else if (metadataResult.Id.Length > 0)
{
// fall back to id
Platform hasheousPlatform = Platforms.GetPlatform(metadataResult.Id);
signature.MetadataSources.AddPlatform((long)hasheousPlatform.Id, hasheousPlatform.Name, metadataResult.Source);
}
else
{
// no id or immutable id - use unknown platform
signature.MetadataSources.AddPlatform(0, "Unknown Platform", HasheousClient.Models.MetadataSources.None);
}
}
}
}
@@ -357,11 +369,20 @@ namespace gaseous_server.Classes
// only IGDB metadata is supported
if (metadataResult.Source == HasheousClient.Models.MetadataSources.IGDB)
{
if (metadataResult.Id.Length > 0)
if (metadataResult.ImmutableId.Length > 0)
{
signature.MetadataSources.AddGame(long.Parse(metadataResult.ImmutableId), HasheousResult.Name, metadataResult.Source);
}
else if (metadataResult.Id.Length > 0)
{
gaseous_server.Models.Game hasheousGame = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, metadataResult.Id);
signature.MetadataSources.AddGame((long)hasheousGame.Id, hasheousGame.Name, metadataResult.Source);
}
else
{
// no id or immutable id - use unknown game
signature.MetadataSources.AddGame(0, "Unknown Game", HasheousClient.Models.MetadataSources.None);
}
}
}
}

View File

@@ -561,7 +561,7 @@ namespace gaseous_server.Classes
{
gameSlug = game.Slug;
}
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, gameSlug, platformSlug);
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, platformSlug);
if (!Directory.Exists(DestinationPath))
{
Directory.CreateDirectory(DestinationPath);

View File

@@ -1110,8 +1110,10 @@ namespace gaseous_server.Classes.Metadata
public async Task<string> GetSpecificImageFromServer(string ImagePath, string ImageId, IGDBAPI_ImageSize size, List<IGDBAPI_ImageSize>? FallbackSizes = null)
{
string originalPath = Path.Combine(ImagePath, IGDBAPI_ImageSize.original.ToString(), ImageId + ".jpg");
string requestedPath = Path.Combine(ImagePath, size.ToString(), ImageId + ".jpg");
string originalPath = Path.Combine(ImagePath, _MetadataSource.ToString(), IGDBAPI_ImageSize.original.ToString());
string originalFilePath = Path.Combine(originalPath, ImageId);
string requestedPath = Path.Combine(ImagePath, _MetadataSource.ToString(), size.ToString());
string requestedFilePath = Path.Combine(requestedPath, ImageId);
// create the directory if it doesn't exist
if (!Directory.Exists(Path.GetDirectoryName(originalPath)))
@@ -1127,7 +1129,7 @@ namespace gaseous_server.Classes.Metadata
Point resolution = Common.GetResolution(size);
// check if the original image exists
if (!File.Exists(originalPath))
if (!File.Exists(originalFilePath))
{
// sleep if the rate limiter is active
if (RateLimitResumeTime > DateTime.UtcNow)
@@ -1147,14 +1149,21 @@ namespace gaseous_server.Classes.Metadata
Communications comms = new Communications();
switch (_MetadataSource)
{
case HasheousClient.Models.MetadataSources.None:
await comms.API_GetURL(ImageId, originalPath);
return originalFilePath;
case HasheousClient.Models.MetadataSources.IGDB:
originalFilePath = originalFilePath + ".jpg";
requestedFilePath = requestedFilePath + ".jpg";
if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false)
{
await comms.IGDBAPI_GetImage(ImageId, ImagePath);
await comms.IGDBAPI_GetImage(ImageId, originalPath);
}
else
{
await comms.HasheousAPI_GetImage(ImageId, ImagePath);
await comms.HasheousAPI_GetImage(ImageId, originalPath);
}
break;
@@ -1164,10 +1173,10 @@ namespace gaseous_server.Classes.Metadata
}
// check if the requested image exists
if (!File.Exists(requestedPath))
if (!File.Exists(requestedFilePath))
{
// get the original image
using (var image = new ImageMagick.MagickImage(originalPath))
using (var image = new ImageMagick.MagickImage(originalFilePath))
{
image.Resize(resolution.X, resolution.Y);
image.Strip();
@@ -1175,7 +1184,7 @@ namespace gaseous_server.Classes.Metadata
}
}
return requestedPath;
return requestedFilePath;
}
public static T? GetSearchCache<T>(string SearchFields, string SearchString)
@@ -1228,6 +1237,80 @@ namespace gaseous_server.Classes.Metadata
db.ExecuteNonQuery(sql, dbDict);
}
public static void PopulateHasheousPlatformData(long Id)
{
// fetch all platforms
ConfigureHasheousClient(ref hasheous);
var hasheousPlatforms = hasheous.GetPlatforms();
foreach (var hasheousPlatform in hasheousPlatforms)
{
// check the metadata attribute for a igdb platform id
if (hasheousPlatform.Metadata != null)
{
foreach (var metadata in hasheousPlatform.Metadata)
{
if (metadata.Source == HasheousClient.Models.MetadataSources.IGDB)
{
if (metadata.ImmutableId.Length > 0)
{
long objId = 0;
long.TryParse(metadata.ImmutableId, out objId);
if (objId == Id)
{
// we have a match - check hasheousPlatform attributes for a logo
foreach (var hasheousPlatformAttribute in hasheousPlatform.Attributes)
{
if (
hasheousPlatformAttribute.attributeType == HasheousClient.Models.AttributeItem.AttributeType.ImageId &&
hasheousPlatformAttribute.attributeName == HasheousClient.Models.AttributeItem.AttributeName.Logo &&
hasheousPlatformAttribute.Value != null
)
{
Uri logoUrl = new Uri(
new Uri(HasheousClient.WebApp.HttpHelper.BaseUri, UriKind.Absolute),
new Uri("/api/v1/images/" + hasheousPlatformAttribute.Value, UriKind.Relative));
// generate a platform logo object
HasheousClient.Models.Metadata.IGDB.PlatformLogo platformLogo = new HasheousClient.Models.Metadata.IGDB.PlatformLogo
{
AlphaChannel = false,
Animated = false,
ImageId = (string)hasheousPlatformAttribute.Value,
Url = logoUrl.ToString()
};
// generate a long id from the value
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(platformLogo.ImageId);
long longId = BitConverter.ToInt64(bytes, 0);
platformLogo.Id = longId;
// store the platform logo object
Storage.CacheStatus cacheStatus = Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.None, "PlatformLogo", longId);
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
Storage.NewCacheValue<PlatformLogo>(HasheousClient.Models.MetadataSources.None, platformLogo, false);
break;
}
// update the platform object
Platform? platform = Platforms.GetPlatform(Id);
if (platform != null)
{
platform.PlatformLogo = platformLogo.Id;
Storage.NewCacheValue<Platform>(HasheousClient.Models.MetadataSources.None, platform, true);
}
}
}
}
}
}
}
}
}
}
/// <summary>
/// See https://api-docs.igdb.com/?javascript#images for more information about the image url structure
/// </summary>
@@ -1238,9 +1321,8 @@ namespace gaseous_server.Classes.Metadata
string urlTemplate = "https://images.igdb.com/igdb/image/upload/t_{size}/{hash}.jpg";
string url = urlTemplate.Replace("{size}", "original").Replace("{hash}", ImageId);
string newOutputPath = Path.Combine(OutputPath, "original");
string OutputFile = ImageId + ".jpg";
string fullPath = Path.Combine(newOutputPath, OutputFile);
string fullPath = Path.Combine(OutputPath, OutputFile);
await _DownloadFile(new Uri(url), fullPath);
}
@@ -1250,9 +1332,19 @@ namespace gaseous_server.Classes.Metadata
string urlTemplate = HasheousClient.WebApp.HttpHelper.BaseUri + "api/v1/MetadataProxy/IGDB/Image/{hash}.jpg";
string url = urlTemplate.Replace("{hash}", ImageId);
string newOutputPath = Path.Combine(OutputPath, "original");
string OutputFile = ImageId + ".jpg";
string fullPath = Path.Combine(newOutputPath, OutputFile);
string fullPath = Path.Combine(OutputPath, OutputFile);
await _DownloadFile(new Uri(url), fullPath);
}
public async Task API_GetURL(string FileName, string OutputPath)
{
string urlTemplate = HasheousClient.WebApp.HttpHelper.BaseUri + "api/v1/images/{imageid}";
string url = urlTemplate.Replace("{imageid}", FileName);
string OutputFile = FileName;
string fullPath = Path.Combine(OutputPath, OutputFile);
await _DownloadFile(new Uri(url), fullPath);
}

View File

@@ -294,12 +294,24 @@ ORDER BY Platform.`Name`;";
if (platform.Id != 0)
{
Models.PlatformMapping.PlatformMapItem platformMap = PlatformMapping.GetPlatformMap((long)platform.Id);
emulatorConfiguration = new PlatformMapping.UserEmulatorConfiguration
if (platformMap != null)
{
EmulatorType = platformMap.WebEmulator.Type,
Core = platformMap.WebEmulator.Core,
EnableBIOSFiles = platformMap.EnabledBIOSHashes
};
emulatorConfiguration = new PlatformMapping.UserEmulatorConfiguration
{
EmulatorType = platformMap.WebEmulator.Type,
Core = platformMap.WebEmulator.Core,
EnableBIOSFiles = platformMap.EnabledBIOSHashes
};
}
else
{
emulatorConfiguration = new PlatformMapping.UserEmulatorConfiguration
{
EmulatorType = "",
Core = "",
EnableBIOSFiles = new List<string>()
};
}
}
}

View File

@@ -93,21 +93,13 @@ namespace gaseous_server.Classes.Metadata
// check cached metadata status
// if metadata is not cached or expired, get it from the source. Otherwise, return the cached metadata
Storage.CacheStatus? cacheStatus;
if (SourceType == HasheousClient.Models.MetadataSources.None)
if (idType == IdType.Long)
{
// if source is None, set cache status to current
cacheStatus = Storage.CacheStatus.Current;
cacheStatus = Storage.GetCacheStatus(SourceType, type, (long)Id);
}
else
{
if (idType == IdType.Long)
{
cacheStatus = Storage.GetCacheStatus(SourceType, type, (long)Id);
}
else
{
cacheStatus = Storage.GetCacheStatus(SourceType, type, (string)Id);
}
cacheStatus = Storage.GetCacheStatus(SourceType, type, (string)Id);
}
// if ForceRefresh is true, set cache status to expired if it is current

View File

@@ -1,5 +1,6 @@
using System;
using HasheousClient.Models.Metadata.IGDB;
using static gaseous_server.Models.PlatformMapping;
namespace gaseous_server.Classes.Metadata
@@ -12,7 +13,7 @@ namespace gaseous_server.Classes.Metadata
{
}
public static PlatformLogo? GetPlatformLogo(long? Id)
public static PlatformLogo? GetPlatformLogo(long? Id, HasheousClient.Models.MetadataSources SourceType = HasheousClient.Models.MetadataSources.IGDB)
{
if ((Id == 0) || (Id == null))
{
@@ -20,7 +21,7 @@ namespace gaseous_server.Classes.Metadata
}
else
{
PlatformLogo? RetVal = Metadata.GetMetadata<PlatformLogo>(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false);
PlatformLogo? RetVal = Metadata.GetMetadata<PlatformLogo>(SourceType, (long)Id, false);
return RetVal;
}
}

View File

@@ -22,7 +22,16 @@ namespace gaseous_server.Classes.Metadata
}
else
{
Platform? RetVal = Metadata.GetMetadata<Platform>(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false);
Platform? RetVal = new Platform();
if (Config.MetadataConfiguration.DefaultMetadataSource == HasheousClient.Models.MetadataSources.None)
{
RetVal = (Platform?)Storage.GetCacheValue<Platform>(HasheousClient.Models.MetadataSources.None, RetVal, "Id", (long)Id);
}
else
{
RetVal = Metadata.GetMetadata<Platform>(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false);
}
return RetVal;
}
}

View File

@@ -127,7 +127,7 @@ namespace gaseous_server.Controllers
try
{
logoObject = PlatformLogos.GetPlatformLogo((long)platformObject.PlatformLogo);
logoObject = PlatformLogos.GetPlatformLogo((long)platformObject.PlatformLogo, Communications.MetadataSource);
}
catch
{
@@ -141,17 +141,17 @@ namespace gaseous_server.Controllers
}
else
{
return NotFound();
return GetDummyImage();
}
}
else
{
return NotFound();
return GetDummyImage();
}
}
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platformObject));
string imagePath = Path.Combine(basePath, size.ToString(), logoObject.ImageId + ".jpg");
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platformObject), Communications.MetadataSource.ToString());
string imagePath = Path.Combine(basePath, size.ToString(), logoObject.ImageId);
if (!System.IO.File.Exists(imagePath))
{
@@ -171,9 +171,71 @@ namespace gaseous_server.Controllers
if (System.IO.File.Exists(imagePath))
{
string filename = logoObject.ImageId + ".jpg";
// get image info
var info = new ImageMagick.MagickImageInfo(imagePath);
string extension = ".jpg";
string mimeType = "image/jpg";
switch (info.Format)
{
case ImageMagick.MagickFormat.Jpeg:
extension = ".jpg";
mimeType = "image/jpg";
break;
case ImageMagick.MagickFormat.Png:
extension = ".png";
mimeType = "image/png";
break;
case ImageMagick.MagickFormat.Gif:
extension = ".gif";
mimeType = "image/gif";
break;
case ImageMagick.MagickFormat.Bmp:
extension = ".bmp";
mimeType = "image/bmp";
break;
case ImageMagick.MagickFormat.Tiff:
extension = ".tiff";
mimeType = "image/tiff";
break;
case ImageMagick.MagickFormat.Unknown:
extension = ".jpg";
mimeType = "image/jpg";
break;
case ImageMagick.MagickFormat.WebP:
extension = ".webp";
mimeType = "image/webp";
break;
case ImageMagick.MagickFormat.Heic:
extension = ".heic";
mimeType = "image/heic";
break;
case ImageMagick.MagickFormat.Heif:
extension = ".heif";
mimeType = "image/heif";
break;
case ImageMagick.MagickFormat.Svg:
extension = ".svg";
mimeType = "image/svg+xml";
break;
default:
extension = ".jpg";
mimeType = "image/jpg";
break;
}
string filename = logoObject.ImageId + extension;
string filepath = imagePath;
string contentType = "image/jpg";
string contentType = mimeType;
var cd = new System.Net.Mime.ContentDisposition
{
@@ -195,14 +257,60 @@ namespace gaseous_server.Controllers
return File(filedata, contentType);
}
return NotFound();
else
{
return NotFound();
}
}
catch
{
return NotFound();
}
}
private ActionResult GetDummyImage()
{
// return resource named DefaultPlatformLogo.svg
var assembly = Assembly.GetExecutingAssembly();
string resourceName = "gaseous_server.Support.DefaultPlatformLogo.svg";
string[] resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
if (resources.Contains(resourceName))
{
string svgData = "";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
svgData = reader.ReadToEnd();
}
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "DefaultPlatformLogo.svg",
Inline = true,
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("Cache-Control", "public, max-age=604800");
byte[] filedata = null;
using (MemoryStream ms = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(ms))
{
writer.Write(svgData);
writer.Flush();
ms.Position = 0;
filedata = ms.ToArray();
}
}
return File(filedata, "image/svg+xml");
}
else
{
return NotFound();
}
}
}
}

View File

@@ -102,9 +102,16 @@ namespace gaseous_server.Models
AlternativeName = mapItem.AlternateNames.FirstOrDefault()
};
if (Storage.GetCacheStatus(Communications.MetadataSource, "Platform", mapItem.IGDBId) == Storage.CacheStatus.NotPresent)
if (Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.None, "Platform", mapItem.IGDBId) == Storage.CacheStatus.NotPresent)
{
Storage.NewCacheValue(Communications.MetadataSource, platform);
Storage.NewCacheValue(HasheousClient.Models.MetadataSources.None, platform);
}
Communications.PopulateHasheousPlatformData(mapItem.IGDBId);
if (Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.IGDB, "Platform", mapItem.IGDBId) == Storage.CacheStatus.NotPresent)
{
Storage.NewCacheValue(HasheousClient.Models.MetadataSources.IGDB, platform);
}
return platform;

View File

@@ -54,6 +54,21 @@ namespace gaseous_server.Models
}
}
if (_flags.PlatformId == 0)
{
// fall back to the IGDB source if present
foreach (SourceValues.SourceValueItem source in MetadataSources.Platforms)
{
if (source.Source == HasheousClient.Models.MetadataSources.IGDB)
{
_flags.PlatformId = source.Id;
_flags.PlatformName = source.Name;
_flags.PlatformMetadataSource = source.Source;
break;
}
}
}
foreach (SourceValues.SourceValueItem source in MetadataSources.Games)
{
if (source.Source == Config.MetadataConfiguration.DefaultMetadataSource)
@@ -65,6 +80,13 @@ namespace gaseous_server.Models
}
}
if (_flags.GameId == null || _flags.GameId == 0)
{
_flags.GameId = 0;
_flags.GameName = "Unknown Game";
_flags.GameMetadataSource = HasheousClient.Models.MetadataSources.None;
}
return _flags;
}
}

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M403.2 803.2c-0.8 0-8.8 64-9.6 65.6-1.6 13.6-4 21.6-11.2 28-2.4 2.4-4.8 3.2-7.2 4.8-5.6 4-10.4 6.4-16.8 10.4-4.8 2.4-10.4 12-4.8 14.4h316.8c5.6-2.4 0-11.2-4.8-13.6-6.4-4-11.2-7.2-16.8-12-2.4-1.6-4.8-4-7.2-6.4-6.4-6.4-9.6-12-11.2-25.6 0-1.6-9.6-71.2-9.6-65.6" fill="#D2D5D6" /><path d="M992 704.8V124c0-14.4-11.2-26.4-25.6-26.4H57.6c-14.4 0-25.6 12-25.6 26.4v581.6" fill="#938993" /><path d="M84 149.6h856v503.2h-856z" fill="#E2D3E2" /><path d="M376 137.6l576 528v-528z" fill="#FAFBFA" /><path d="M32 704v72.8c0 14.4 11.2 26.4 25.6 26.4h908c14.4 0 25.6-12 25.6-26.4V704" fill="#D2D5D6" /><path d="M511.2 754.4m-24 0a24 24 0 1 0 48 0 24 24 0 1 0-48 0Z" fill="#414343" /><path d="M623.2 827.2c-0.8-24-1.6-24-1.6-24H404s-0.8 0-1.6 24h220.8z" fill="#0D1014" /><path d="M449.6 568.8l-1.6 4z" fill="#99D9E6" /><path d="M353.6 934.4c-0.8 0-2.4 0-3.2-0.8-4-1.6-7.2-5.6-7.2-10.4 0-8 6.4-16 11.2-18.4l3.2-1.6c4.8-2.4 8.8-4.8 12-8 1.6-0.8 2.4-1.6 4-2.4 0.8-0.8 1.6-0.8 2.4-1.6 4.8-4 6.4-10.4 8-22.4 8-67.2 8-67.2 16-67.2 4.8 0 8 3.2 8 8v2.4c-0.8 5.6-7.2 54.4-8 58.4-1.6 14.4-4.8 24.8-13.6 32.8-1.6 1.6-4 3.2-5.6 4-0.8 0.8-1.6 0.8-2.4 1.6-4.8 4-9.6 6.4-14.4 8.8l-3.2 1.6H656c-5.6-3.2-10.4-7.2-15.2-10.4-1.6-1.6-3.2-3.2-5.6-4.8l-2.4-1.6c-8.8-8-12-16.8-13.6-30.4-0.8-4-6.4-48.8-8-58.4 0-0.8-0.8-1.6-0.8-3.2 0-4 3.2-8 7.2-8.8 8.8-0.8 8.8-0.8 16.8 67.2 1.6 12.8 4 16.8 8 20.8l2.4 2.4c1.6 1.6 3.2 2.4 4 4 5.6 4 9.6 7.2 16 11.2 4.8 2.4 12 10.4 11.2 17.6 0 4.8-3.2 8-7.2 10.4-0.8 0.8-2.4 0.8-3.2 0.8l-312-1.6zM992 712.8c-4.8 0-8-3.2-8-8V124c0-10.4-8-18.4-17.6-18.4H57.6c-9.6 0-17.6 8-17.6 18.4v581.6c0 4.8-3.2 8-8 8s-8-3.2-8-8V124c0-19.2 15.2-34.4 33.6-34.4h908c18.4 0 33.6 15.2 33.6 34.4v581.6c0.8 4-2.4 7.2-7.2 7.2z" fill="#6A576D" /><path d="M940 660.8h-856c-4.8 0-8-3.2-8-8V149.6c0-4.8 3.2-8 8-8h856c4.8 0 8 3.2 8 8v503.2c0 4.8-4 8-8 8z m-848-16h840V157.6h-840v487.2zM966.4 811.2H57.6c-18.4 0-33.6-15.2-33.6-34.4V704c0-4.8 3.2-8 8-8h960c4.8 0 8 3.2 8 8v72.8c0 19.2-15.2 34.4-33.6 34.4zM40 712v64.8c0 10.4 8 18.4 17.6 18.4h908c9.6 0 17.6-8 17.6-18.4V712H40z" fill="#6A576D" /></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -20,7 +20,7 @@
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="gaseous-signature-parser" Version="2.3.0" />
<PackageReference Include="gaseous.IGDB" Version="1.0.2" />
<PackageReference Include="hasheous-client" Version="1.2.1" />
<PackageReference Include="hasheous-client" Version="1.2.2" />
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.8.0" />
<PackageReference Include="sharpcompress" Version="0.37.2" />
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.2.24" />
@@ -92,6 +92,7 @@
</EmbeddedResource>
<EmbeddedResource Include="Support\Country.txt" />
<EmbeddedResource Include="Support\Language.txt" />
<EmbeddedResource Include="Support\DefaultPlatformLogo.svg" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />

View File

@@ -15,6 +15,7 @@ function loadPlatformMapping(Overwrite) {
createTableRow(
true,
[
'',
'Platform',
'Supported File Extensions',
'Unique File Extensions',
@@ -27,6 +28,12 @@ function loadPlatformMapping(Overwrite) {
);
for (let i = 0; i < result.length; i++) {
let logo = document.createElement('img');
logo.src = '/api/v1.1/Platforms/' + result[i].igdbId + '/platformlogo/original/logo.png';
logo.alt = result[i].igdbName;
logo.title = result[i].igdbName;
logo.classList.add('platform_image');
let hasWebEmulator = '';
if (result[i].webEmulator.type.length > 0) {
hasWebEmulator = 'Yes';
@@ -49,6 +56,7 @@ function loadPlatformMapping(Overwrite) {
}
let newRow = [
logo,
result[i].igdbName,
result[i].extensions.supportedFileExtensions.join(', '),
result[i].extensions.uniqueFileExtensions.join(', '),

View File

@@ -2930,6 +2930,7 @@ button:not(.select2-selection__choice__remove):not(.select2-selection__clear):no
cursor: pointer;
display: flex;
gap: 20px;
padding-left: 0;
align-items: center;
position: relative;
overflow: hidden;
@@ -2946,15 +2947,24 @@ button:not(.select2-selection__choice__remove):not(.select2-selection__clear):no
.platform_item_background:hover {}
.platform_image_container {
margin-left: 10px;
margin-right: 10px;
max-width: 50px;
max-height: 50px;
width: 70px;
height: 70px;
flex-grow: 0;
/* text-align: center;
vertical-align: middle;
line-height: 75px; */
display: flex;
justify-content: center;
align-items: center;
padding-left: 20px;
padding-right: 20px;
background-color: white;
}
.platform_image {
width: 40px;
width: 70px;
}
.platform_name_container {