Files

190 lines
6.2 KiB
Plaintext

@inject IJSRuntime js
<div class="flex p-64 h-screen w-screen">
<div id="dropzone" name="file" class="w-full h-96 bg-gray-300 rounded-2xl " type="file"></div>
<img id="cropped-image" class="w-full h-screen py-60" src="" alt="">
<div id="cropped" class="hidden">
<img id="cropped-image" class="w-full h-96" src="" alt="">
<div class="flex">
<button type="button" @onclick="RemoveCropped" class="btn btn-primary">test</button>
</div>
</div>
</div>
@code {
[Parameter]
public string UploadLink { get; set; }
protected override async Task OnInitializedAsync()
{
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await js.InvokeVoidAsync("startCropper");
}
}
async Task RemoveCropped()
{
await js.InvokeVoidAsync("removeCropped");
}
public async Task<string> UploadPhoto()
{
var photoLink = "";
return photoLink;
}
}
@* @namespace MediaComponentLib
@using Microsoft.Extensions.Localization
@using Microsoft.AspNetCore.Components.Forms
@inject IStringLocalizer<Cropper> Loc
@inject IJSRuntime JSRuntime
@implements IAsyncDisposable
<div class="flex flex-col p-4 w-full h-full min-h-[500px] items-center gap-4">
@if (string.IsNullOrEmpty(_imageData))
{
<div
class="w-full h-64 bg-gray-100 rounded-2xl flex flex-col items-center justify-center relative border-2 border-dashed border-gray-300 hover:bg-gray-50 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-gray-400 mb-2" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
<span class="text-lg text-gray-500 font-medium">Drop image here or click to upload</span>
<InputFile class="absolute inset-0 w-full h-full opacity-0 cursor-pointer z-10" OnChange="HandleFileSelected"
accept=".jpg,.jpeg,.png,.webp" />
</div>
}
else if (!_isCropped)
{
<div class="w-full flex-1 bg-black rounded-lg overflow-hidden relative" style="min-height: 400px;">
<!-- Unique ID used by Interop -->
<img id="@_uniqueId" src="@_imageData" @onload="OnImageLoaded" class="max-w-full max-h-full block mx-auto"
style="display: block;" />
</div>
<div class="flex gap-2 w-full justify-end">
<button class="btn btn-ghost" @onclick="Reset">@Loc["Cancel"]</button>
<button class="btn btn-primary" @onclick="CropImage">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
@Loc["Crop"]
</button>
</div>
}
else
{
<div class="flex flex-col gap-4 items-center w-full">
<div class="bg-base-200 p-2 rounded-lg shadow-sm">
<img src="@_croppedData" class="max-w-full max-h-[500px] rounded" />
</div>
<button class="btn btn-warning" @onclick="Reset">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
@Loc["Remove"]
</button>
</div>
}
</div>
@code {
[Parameter] public string? UploadLink { get; set; }
// Unique ID for this instance
private string _uniqueId = "cropper-" + Guid.NewGuid().ToString("N");
private string? _imageData;
private string? _croppedData;
private bool _isCropped;
private MediaJsInterop? _mediaInterop;
private DotNetObjectReference<Cropper>? _objRef;
protected override void OnInitialized()
{
_mediaInterop = new MediaJsInterop(JSRuntime);
_objRef = DotNetObjectReference.Create(this);
}
private async Task HandleFileSelected(InputFileChangeEventArgs e)
{
try
{
var file = e.File;
if (file == null) return;
// Limit to 10MB
var maxFileSize = 10L * 1024 * 1024;
var stream = file.OpenReadStream(maxFileSize);
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var base64 = Convert.ToBase64String(ms.ToArray());
_imageData = $"data:{file.ContentType};base64,{base64}";
_isCropped = false;
}
catch (Exception ex)
{
Console.WriteLine($"Error reading file: {ex.Message}");
}
}
private async Task OnImageLoaded()
{
if (_mediaInterop != null && !string.IsNullOrEmpty(_imageData))
{
// Small delay to ensure render limits are applied by browser
await Task.Delay(50);
await _mediaInterop.InitCropperAsync(_uniqueId, 16.0 / 9.0, _objRef!);
}
}
private async Task CropImage()
{
if (_mediaInterop != null)
{
_croppedData = await _mediaInterop.GetCroppedImageAsync();
await _mediaInterop.DestroyCropperAsync();
_isCropped = true;
}
}
private async Task Reset()
{
if (_mediaInterop != null)
await _mediaInterop.DestroyCropperAsync();
_imageData = null;
_croppedData = null;
_isCropped = false;
}
public async ValueTask DisposeAsync()
{
if (_mediaInterop != null)
{
try { await _mediaInterop.DestroyCropperAsync(); } catch { }
}
_objRef?.Dispose();
}
} *@