Compare commits
3 Commits
b25b08b5c5
...
c4f6798fd0
| Author | SHA1 | Date | |
|---|---|---|---|
| c4f6798fd0 | |||
| 130ad8f186 | |||
| 09e4150294 |
@@ -27,7 +27,7 @@ public enum NotificationPushProvider
|
|||||||
Google
|
Google
|
||||||
}
|
}
|
||||||
|
|
||||||
[Index(nameof(DeviceToken), nameof(DeviceId), IsUnique = true)]
|
[Index(nameof(DeviceToken), nameof(DeviceId), nameof(AccountId), IsUnique = true)]
|
||||||
public class NotificationPushSubscription : ModelBase
|
public class NotificationPushSubscription : ModelBase
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; } = Guid.NewGuid();
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ public class NotificationService(
|
|||||||
// Reset these audit fields to renew the lifecycle of this device token
|
// Reset these audit fields to renew the lifecycle of this device token
|
||||||
existingSubscription.DeviceId = deviceId;
|
existingSubscription.DeviceId = deviceId;
|
||||||
existingSubscription.DeviceToken = deviceToken;
|
existingSubscription.DeviceToken = deviceToken;
|
||||||
existingSubscription.UpdatedAt = SystemClock.Instance.GetCurrentInstant();
|
|
||||||
db.Update(existingSubscription);
|
db.Update(existingSubscription);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
return existingSubscription;
|
return existingSubscription;
|
||||||
|
|||||||
3394
DysonNetwork.Sphere/Migrations/20250602144445_FixPushNotificationIndex.Designer.cs
generated
Normal file
3394
DysonNetwork.Sphere/Migrations/20250602144445_FixPushNotificationIndex.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class FixPushNotificationIndex : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "ix_notification_push_subscriptions_device_token_device_id",
|
||||||
|
table: "notification_push_subscriptions");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_notification_push_subscriptions_device_token_device_id_acco",
|
||||||
|
table: "notification_push_subscriptions",
|
||||||
|
columns: new[] { "device_token", "device_id", "account_id" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "ix_notification_push_subscriptions_device_token_device_id_acco",
|
||||||
|
table: "notification_push_subscriptions");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_notification_push_subscriptions_device_token_device_id",
|
||||||
|
table: "notification_push_subscriptions",
|
||||||
|
columns: new[] { "device_token", "device_id" },
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,18 +12,19 @@ namespace DysonNetwork.Sphere.Sticker;
|
|||||||
[Route("/stickers")]
|
[Route("/stickers")]
|
||||||
public class StickerController(AppDatabase db, StickerService st) : ControllerBase
|
public class StickerController(AppDatabase db, StickerService st) : ControllerBase
|
||||||
{
|
{
|
||||||
private async Task<IActionResult> _CheckStickerPackPermissions(Guid packId, Account.Account currentUser, PublisherMemberRole requiredRole)
|
private async Task<IActionResult> _CheckStickerPackPermissions(Guid packId, Account.Account currentUser,
|
||||||
|
PublisherMemberRole requiredRole)
|
||||||
{
|
{
|
||||||
var pack = await db.StickerPacks
|
var pack = await db.StickerPacks
|
||||||
.Include(p => p.Publisher)
|
.Include(p => p.Publisher)
|
||||||
.FirstOrDefaultAsync(p => p.Id == packId);
|
.FirstOrDefaultAsync(p => p.Id == packId);
|
||||||
|
|
||||||
if (pack is null)
|
if (pack is null)
|
||||||
return NotFound("Sticker pack not found");
|
return NotFound("Sticker pack not found");
|
||||||
|
|
||||||
var member = await db.PublisherMembers
|
var member = await db.PublisherMembers
|
||||||
.FirstOrDefaultAsync(m => m.AccountId == currentUser.Id && m.PublisherId == pack.PublisherId);
|
.FirstOrDefaultAsync(m => m.AccountId == currentUser.Id && m.PublisherId == pack.PublisherId);
|
||||||
if (member is null)
|
if (member is null)
|
||||||
return StatusCode(403, "You are not a member of this publisher");
|
return StatusCode(403, "You are not a member of this publisher");
|
||||||
if (member.Role < requiredRole)
|
if (member.Role < requiredRole)
|
||||||
return StatusCode(403, $"You need to be at least a {requiredRole} to perform this action");
|
return StatusCode(403, $"You need to be at least a {requiredRole} to perform this action");
|
||||||
@@ -32,11 +33,21 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<List<StickerPack>>> ListStickerPacks([FromQuery] int offset = 0,
|
public async Task<ActionResult<List<StickerPack>>> ListStickerPacks(
|
||||||
[FromQuery] int take = 20)
|
[FromQuery] int offset = 0,
|
||||||
|
[FromQuery] int take = 20,
|
||||||
|
[FromQuery] string? pubName = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var totalCount = await db.StickerPacks.CountAsync();
|
Publisher.Publisher? publisher = null;
|
||||||
|
if (pubName is not null)
|
||||||
|
publisher = await db.Publishers.FirstOrDefaultAsync(p => p.Name == pubName);
|
||||||
|
|
||||||
|
var totalCount = await db.StickerPacks
|
||||||
|
.If(publisher is not null, q => q.Where(f => f.PublisherId == publisher!.Id))
|
||||||
|
.CountAsync();
|
||||||
var packs = await db.StickerPacks
|
var packs = await db.StickerPacks
|
||||||
|
.If(publisher is not null, q => q.Where(f => f.PublisherId == publisher!.Id))
|
||||||
.OrderByDescending(e => e.CreatedAt)
|
.OrderByDescending(e => e.CreatedAt)
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
@@ -95,22 +106,22 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
return Ok(pack);
|
return Ok(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPatch("{id:guid}")]
|
[HttpPatch("{id:guid}")]
|
||||||
public async Task<ActionResult<StickerPack>> UpdateStickerPack(Guid id, [FromBody] StickerPackRequest request)
|
public async Task<ActionResult<StickerPack>> UpdateStickerPack(Guid id, [FromBody] StickerPackRequest request)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
var pack = await db.StickerPacks
|
var pack = await db.StickerPacks
|
||||||
.Include(p => p.Publisher)
|
.Include(p => p.Publisher)
|
||||||
.FirstOrDefaultAsync(p => p.Id == id);
|
.FirstOrDefaultAsync(p => p.Id == id);
|
||||||
if (pack is null)
|
if (pack is null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
var member = await db.PublisherMembers
|
var member = await db.PublisherMembers
|
||||||
.FirstOrDefaultAsync(m => m.AccountId == currentUser.Id && m.PublisherId == pack.PublisherId);
|
.FirstOrDefaultAsync(m => m.AccountId == currentUser.Id && m.PublisherId == pack.PublisherId);
|
||||||
if (member is null)
|
if (member is null)
|
||||||
return StatusCode(403, "You are not a member of this publisher");
|
return StatusCode(403, "You are not a member of this publisher");
|
||||||
if (member.Role < PublisherMemberRole.Editor)
|
if (member.Role < PublisherMemberRole.Editor)
|
||||||
return StatusCode(403, "You need to be at least an editor to update sticker packs");
|
return StatusCode(403, "You need to be at least an editor to update sticker packs");
|
||||||
@@ -126,22 +137,22 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
return Ok(pack);
|
return Ok(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("{id:guid}")]
|
[HttpDelete("{id:guid}")]
|
||||||
public async Task<IActionResult> DeleteStickerPack(Guid id)
|
public async Task<IActionResult> DeleteStickerPack(Guid id)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
var pack = await db.StickerPacks
|
var pack = await db.StickerPacks
|
||||||
.Include(p => p.Publisher)
|
.Include(p => p.Publisher)
|
||||||
.FirstOrDefaultAsync(p => p.Id == id);
|
.FirstOrDefaultAsync(p => p.Id == id);
|
||||||
if (pack is null)
|
if (pack is null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
var member = await db.PublisherMembers
|
var member = await db.PublisherMembers
|
||||||
.FirstOrDefaultAsync(m => m.AccountId == currentUser.Id && m.PublisherId == pack.PublisherId);
|
.FirstOrDefaultAsync(m => m.AccountId == currentUser.Id && m.PublisherId == pack.PublisherId);
|
||||||
if (member is null)
|
if (member is null)
|
||||||
return StatusCode(403, "You are not a member of this publisher");
|
return StatusCode(403, "You are not a member of this publisher");
|
||||||
if (member.Role < PublisherMemberRole.Editor)
|
if (member.Role < PublisherMemberRole.Editor)
|
||||||
return StatusCode(403, "You need to be an editor to delete sticker packs");
|
return StatusCode(403, "You need to be an editor to delete sticker packs");
|
||||||
@@ -162,21 +173,21 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
|
|
||||||
return Ok(stickers);
|
return Ok(stickers);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("lookup/{identifier}")]
|
[HttpGet("lookup/{identifier}")]
|
||||||
public async Task<ActionResult<Sticker>> GetStickerByIdentifier(string identifier)
|
public async Task<ActionResult<Sticker>> GetStickerByIdentifier(string identifier)
|
||||||
{
|
{
|
||||||
var sticker = await st.LookupStickerByIdentifierAsync(identifier);
|
var sticker = await st.LookupStickerByIdentifierAsync(identifier);
|
||||||
|
|
||||||
if (sticker is null) return NotFound();
|
if (sticker is null) return NotFound();
|
||||||
return Ok(sticker);
|
return Ok(sticker);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("lookup/{identifier}/open")]
|
[HttpGet("lookup/{identifier}/open")]
|
||||||
public async Task<ActionResult<Sticker>> OpenStickerByIdentifier(string identifier)
|
public async Task<ActionResult<Sticker>> OpenStickerByIdentifier(string identifier)
|
||||||
{
|
{
|
||||||
var sticker = await st.LookupStickerByIdentifierAsync(identifier);
|
var sticker = await st.LookupStickerByIdentifierAsync(identifier);
|
||||||
|
|
||||||
if (sticker is null) return NotFound();
|
if (sticker is null) return NotFound();
|
||||||
return Redirect($"/files/{sticker.ImageId}");
|
return Redirect($"/files/{sticker.ImageId}");
|
||||||
}
|
}
|
||||||
@@ -203,11 +214,11 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
[HttpPatch("{packId:guid}/content/{id:guid}")]
|
[HttpPatch("{packId:guid}/content/{id:guid}")]
|
||||||
public async Task<IActionResult> UpdateSticker(Guid packId, Guid id, [FromBody] StickerRequest request)
|
public async Task<IActionResult> UpdateSticker(Guid packId, Guid id, [FromBody] StickerRequest request)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
var permissionCheck = await _CheckStickerPackPermissions(packId, currentUser, PublisherMemberRole.Editor);
|
var permissionCheck = await _CheckStickerPackPermissions(packId, currentUser, PublisherMemberRole.Editor);
|
||||||
if (permissionCheck is not OkResult)
|
if (permissionCheck is not OkResult)
|
||||||
return permissionCheck;
|
return permissionCheck;
|
||||||
|
|
||||||
var sticker = await db.Stickers
|
var sticker = await db.Stickers
|
||||||
@@ -215,13 +226,13 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
.Include(s => s.Pack)
|
.Include(s => s.Pack)
|
||||||
.ThenInclude(p => p.Publisher)
|
.ThenInclude(p => p.Publisher)
|
||||||
.FirstOrDefaultAsync(e => e.Id == id && e.Pack.Id == packId);
|
.FirstOrDefaultAsync(e => e.Id == id && e.Pack.Id == packId);
|
||||||
|
|
||||||
if (sticker is null)
|
if (sticker is null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
if (request.Slug is not null)
|
if (request.Slug is not null)
|
||||||
sticker.Slug = request.Slug;
|
sticker.Slug = request.Slug;
|
||||||
|
|
||||||
CloudFile? image = null;
|
CloudFile? image = null;
|
||||||
if (request.ImageId is not null)
|
if (request.ImageId is not null)
|
||||||
{
|
{
|
||||||
@@ -238,11 +249,11 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
[HttpDelete("{packId:guid}/content/{id:guid}")]
|
[HttpDelete("{packId:guid}/content/{id:guid}")]
|
||||||
public async Task<IActionResult> DeleteSticker(Guid packId, Guid id)
|
public async Task<IActionResult> DeleteSticker(Guid packId, Guid id)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
var permissionCheck = await _CheckStickerPackPermissions(packId, currentUser, PublisherMemberRole.Editor);
|
var permissionCheck = await _CheckStickerPackPermissions(packId, currentUser, PublisherMemberRole.Editor);
|
||||||
if (permissionCheck is not OkResult)
|
if (permissionCheck is not OkResult)
|
||||||
return permissionCheck;
|
return permissionCheck;
|
||||||
|
|
||||||
var sticker = await db.Stickers
|
var sticker = await db.Stickers
|
||||||
@@ -250,8 +261,8 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
.Include(s => s.Pack)
|
.Include(s => s.Pack)
|
||||||
.ThenInclude(p => p.Publisher)
|
.ThenInclude(p => p.Publisher)
|
||||||
.FirstOrDefaultAsync(e => e.Id == id && e.Pack.Id == packId);
|
.FirstOrDefaultAsync(e => e.Id == id && e.Pack.Id == packId);
|
||||||
|
|
||||||
if (sticker is null)
|
if (sticker is null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
|
|
||||||
await st.DeleteStickerAsync(sticker);
|
await st.DeleteStickerAsync(sticker);
|
||||||
@@ -264,30 +275,30 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
[RequiredPermission("global", "stickers.create")]
|
[RequiredPermission("global", "stickers.create")]
|
||||||
public async Task<IActionResult> CreateSticker(Guid packId, [FromBody] StickerRequest request)
|
public async Task<IActionResult> CreateSticker(Guid packId, [FromBody] StickerRequest request)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(request.Slug))
|
if (string.IsNullOrWhiteSpace(request.Slug))
|
||||||
return BadRequest("Slug is required.");
|
return BadRequest("Slug is required.");
|
||||||
if (request.ImageId is null)
|
if (request.ImageId is null)
|
||||||
return BadRequest("Image is required.");
|
return BadRequest("Image is required.");
|
||||||
|
|
||||||
var permissionCheck = await _CheckStickerPackPermissions(packId, currentUser, PublisherMemberRole.Editor);
|
var permissionCheck = await _CheckStickerPackPermissions(packId, currentUser, PublisherMemberRole.Editor);
|
||||||
if (permissionCheck is not OkResult)
|
if (permissionCheck is not OkResult)
|
||||||
return permissionCheck;
|
return permissionCheck;
|
||||||
|
|
||||||
var pack = await db.StickerPacks
|
var pack = await db.StickerPacks
|
||||||
.Include(p => p.Publisher)
|
.Include(p => p.Publisher)
|
||||||
.FirstOrDefaultAsync(e => e.Id == packId);
|
.FirstOrDefaultAsync(e => e.Id == packId);
|
||||||
if (pack is null)
|
if (pack is null)
|
||||||
return BadRequest("Sticker pack was not found.");
|
return BadRequest("Sticker pack was not found.");
|
||||||
|
|
||||||
var stickersCount = await db.Stickers.CountAsync(s => s.PackId == packId);
|
var stickersCount = await db.Stickers.CountAsync(s => s.PackId == packId);
|
||||||
if (stickersCount >= MaxStickersPerPack)
|
if (stickersCount >= MaxStickersPerPack)
|
||||||
return BadRequest($"Sticker pack has reached maximum capacity of {MaxStickersPerPack} stickers.");
|
return BadRequest($"Sticker pack has reached maximum capacity of {MaxStickersPerPack} stickers.");
|
||||||
|
|
||||||
var image = await db.Files.FirstOrDefaultAsync(e => e.Id == request.ImageId);
|
var image = await db.Files.FirstOrDefaultAsync(e => e.Id == request.ImageId);
|
||||||
if (image is null)
|
if (image is null)
|
||||||
return BadRequest("Image was not found.");
|
return BadRequest("Image was not found.");
|
||||||
|
|
||||||
var sticker = new Sticker
|
var sticker = new Sticker
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Minio;
|
using Minio;
|
||||||
using Minio.DataModel.Args;
|
using Minio.DataModel.Args;
|
||||||
|
using NetVips;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using tusdotnet.Stores;
|
using tusdotnet.Stores;
|
||||||
@@ -51,6 +52,7 @@ public class FileService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string TempFilePrefix = "dyn-cloudfile";
|
private static readonly string TempFilePrefix = "dyn-cloudfile";
|
||||||
|
private static readonly string[] function = new[] { "image/gif", "image/apng", "image/webp", "image/avif" };
|
||||||
|
|
||||||
// The analysis file method no longer will remove the GPS EXIF data
|
// The analysis file method no longer will remove the GPS EXIF data
|
||||||
// It should be handled on the client side, and for some specific cases it should be keep
|
// It should be handled on the client side, and for some specific cases it should be keep
|
||||||
@@ -110,7 +112,7 @@ public class FileService(
|
|||||||
var format = vipsImage.Get("vips-loader") ?? "unknown";
|
var format = vipsImage.Get("vips-loader") ?? "unknown";
|
||||||
|
|
||||||
// Try to get orientation from exif data
|
// Try to get orientation from exif data
|
||||||
int orientation = 1;
|
var orientation = 1;
|
||||||
Dictionary<string, object> exif = [];
|
Dictionary<string, object> exif = [];
|
||||||
|
|
||||||
foreach (var field in vipsImage.GetFields())
|
foreach (var field in vipsImage.GetFields())
|
||||||
@@ -177,10 +179,12 @@ public class FileService(
|
|||||||
if (contentType.Split('/')[0] == "image")
|
if (contentType.Split('/')[0] == "image")
|
||||||
{
|
{
|
||||||
// Skip compression for animated image types
|
// Skip compression for animated image types
|
||||||
var animatedMimeTypes = new[] { "image/gif", "image/apng", "image/webp", "image/avif" };
|
var animatedMimeTypes = function;
|
||||||
if (animatedMimeTypes.Contains(contentType))
|
if (animatedMimeTypes.Contains(contentType))
|
||||||
{
|
{
|
||||||
logger.LogInformation("File {fileId} is an animated image (MIME: {mime}), skipping WebP conversion.", fileId, contentType);
|
logger.LogInformation(
|
||||||
|
"File {fileId} is an animated image (MIME: {mime}), skipping WebP conversion.", fileId,
|
||||||
|
contentType);
|
||||||
var tempFilePath = Path.Join(Path.GetTempPath(), $"{TempFilePrefix}#{file.Id}");
|
var tempFilePath = Path.Join(Path.GetTempPath(), $"{TempFilePrefix}#{file.Id}");
|
||||||
result.Add((tempFilePath, string.Empty));
|
result.Add((tempFilePath, string.Empty));
|
||||||
return;
|
return;
|
||||||
@@ -190,7 +194,8 @@ public class FileService(
|
|||||||
|
|
||||||
using var vipsImage = NetVips.Image.NewFromFile(ogFilePath);
|
using var vipsImage = NetVips.Image.NewFromFile(ogFilePath);
|
||||||
var imagePath = Path.Join(Path.GetTempPath(), $"{TempFilePrefix}#{file.Id}");
|
var imagePath = Path.Join(Path.GetTempPath(), $"{TempFilePrefix}#{file.Id}");
|
||||||
vipsImage.WriteToFile(imagePath + ".webp");
|
vipsImage.WriteToFile(imagePath + ".webp",
|
||||||
|
new VOption { { "lossless", true } });
|
||||||
result.Add((imagePath + ".webp", string.Empty));
|
result.Add((imagePath + ".webp", string.Empty));
|
||||||
|
|
||||||
if (vipsImage.Width * vipsImage.Height >= 1024 * 1024)
|
if (vipsImage.Width * vipsImage.Height >= 1024 * 1024)
|
||||||
@@ -201,7 +206,8 @@ public class FileService(
|
|||||||
|
|
||||||
// Create and save image within the same synchronous block to avoid disposal issues
|
// Create and save image within the same synchronous block to avoid disposal issues
|
||||||
using var compressedImage = vipsImage.Resize(scale);
|
using var compressedImage = vipsImage.Resize(scale);
|
||||||
compressedImage.WriteToFile(imageCompressedPath + ".webp");
|
compressedImage.WriteToFile(imageCompressedPath + ".webp",
|
||||||
|
new VOption { { "Q", 80 } });
|
||||||
|
|
||||||
result.Add((imageCompressedPath + ".webp", ".compressed"));
|
result.Add((imageCompressedPath + ".webp", ".compressed"));
|
||||||
file.HasCompression = true;
|
file.HasCompression = true;
|
||||||
@@ -408,7 +414,7 @@ public class FileService(
|
|||||||
|
|
||||||
return client.Build();
|
return client.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method to purge the cache for a specific file
|
// Helper method to purge the cache for a specific file
|
||||||
// Made internal to allow FileReferenceService to use it
|
// Made internal to allow FileReferenceService to use it
|
||||||
internal async Task _PurgeCacheAsync(string fileId)
|
internal async Task _PurgeCacheAsync(string fileId)
|
||||||
@@ -492,4 +498,4 @@ public class FileService(
|
|||||||
.Where(r => r.FileId == fileId)
|
.Where(r => r.FileId == fileId)
|
||||||
.AnyAsync();
|
.AnyAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user