-
+
+
+ @*
-
- @if(File != null){
+
*@
+ @if(File != null && Base64File != null && FileSize != null){
+
- @File.ContentType (@formatSizeUnits(File.Size))
+ @File.ContentType (@formatSizeUnits(FileSize))
}
@@ -38,7 +41,17 @@
@code {
- private IBrowserFile? File { get; set; }
+ // private IBrowserFile? File { get; set; }
+ private FileResult? File { get; set; }
+ private string? Base64File { get; set; }
+ private long? FileSize { get; set; }
+ private string? Base64Url {
+ get {
+ if(File == null || Base64File == null) return null;
+
+ return $"data:{File.ContentType};base64,{Base64File}";
+ }
+ }
private string Description { get; set; }
private bool loading = false;
[Parameter]
@@ -65,11 +78,12 @@
}
- private async Task ChangeFile(InputFileChangeEventArgs e){
- File = e.File;
- }
+ // private async Task ChangeFile(InputFileChangeEventArgs e){
+ // File = e.File;
+ // }
- private string formatSizeUnits(long bytes){
+ private string formatSizeUnits(long? bytes){
+ if(bytes == null) return "?? bytes";
string formatted = "0 bytes";
if (bytes >= 1073741824) { formatted = $"{(bytes / 1073741824):.##} GB"; }
else if (bytes >= 1048576) { formatted = $"{(bytes / 1048576):.##} MB"; }
@@ -79,4 +93,21 @@
return formatted;
}
+
+
+
+ private async Task PicFromMedia(EventArgs e) {
+ File = await MediaPicker.Default.PickPhotoAsync();
+ await PopulateFileDetails();
+ }
+
+ private async Task PicFromPhoto(EventArgs e) {
+ File = await MediaPicker.Default.CapturePhotoAsync();
+ await PopulateFileDetails();
+ }
+
+ private async Task PopulateFileDetails() {
+ FileSize = await State.FileSize(File);
+ Base64File = await State.Base64FromFile(File);
+ }
}
diff --git a/Components/Pages/Person.razor b/Components/Pages/Person.razor
index e06fdd6..e4aaaab 100644
--- a/Components/Pages/Person.razor
+++ b/Components/Pages/Person.razor
@@ -34,7 +34,10 @@
+
diff --git a/Components/PicCard.razor b/Components/PicCard.razor
new file mode 100644
index 0000000..a25aa6a
--- /dev/null
+++ b/Components/PicCard.razor
@@ -0,0 +1,50 @@
+@inject IJSRuntime JS
+
+
+
+
+
+
+@code {
+ [Parameter]
+ public Pic Pic {get; set;}
+ [Parameter]
+ public bool Editable { get; set; } = false;
+ [Parameter]
+ public EditPicDialog? Dialog { get; set; }
+
+ private async Task EditPic(EventArgs e){
+ Dialog.Pic = Pic;
+ // await InvokeAsync(StateHasChanged);
+ await JS.InvokeVoidAsync("ui", "#" + Dialog?.id);
+ }
+
+ public async Task ShareClick(EventArgs e){
+ await Share.Default.RequestAsync(new ShareTextRequest{
+ Uri = Pic.Url,
+ Text = Pic.Description,
+ Title = "I saw this on some.pics",
+ Subject = "I saw this on some.pics"
+ });
+ }
+}
diff --git a/Components/PicList.razor b/Components/PicList.razor
index f6e9d8f..2919ecd 100644
--- a/Components/PicList.razor
+++ b/Components/PicList.razor
@@ -1,29 +1,20 @@
-
+@inject IJSRuntime JS
+
-
-
-
-
+
-
+
@code {
[Parameter]
public Func>> PicsFunc { get; set; }
+ [Parameter]
+ public bool Editable { get; set; } = false;
+ [Parameter]
+ public EditPicDialog? Dialog { get; set; }
private async ValueTask> GetPics(ItemsProviderRequest request) {
return await this.PicsFunc(request);
diff --git a/Components/StatusCard.razor b/Components/StatusCard.razor
index 377c379..8e909a0 100644
--- a/Components/StatusCard.razor
+++ b/Components/StatusCard.razor
@@ -15,10 +15,22 @@
Respond
+
+
@code {
[Parameter]
public Status status { get; set; }
+
+ public async Task ShareClick(EventArgs e){
+ await Share.Default.RequestAsync(new ShareTextRequest{
+ Text = $"{status.Content}\n- from [@{status.Address}]({status.Url})",
+ Title = "I saw this on status.lol",
+ Subject = "I saw this on status.lol"
+ });
+ }
}
diff --git a/Models/State.cs b/Models/State.cs
index 4f6b5f7..acb435c 100644
--- a/Models/State.cs
+++ b/Models/State.cs
@@ -117,8 +117,8 @@ namespace Neighbourhood.omg.lol.Models {
}
public async Task?> GetPics(bool forceRefresh = false) {
- RestService api = new RestService();
if(forceRefresh || this.Pics == null || this.Pics.Count == 0) {
+ RestService api = new RestService();
this.Pics = await api.SomePics();
}
return this.Pics;
@@ -147,6 +147,19 @@ namespace Neighbourhood.omg.lol.Models {
}
}
+ public async Task FileSize(FileResult file) {
+ using var fileStream = await file.OpenReadAsync();
+ return fileStream.Length;
+ }
+
+ public async Task Base64FromFile(FileResult file) {
+ using var memoryStream = new MemoryStream();
+ using var fileStream = await file.OpenReadAsync();
+ await fileStream.CopyToAsync(memoryStream);
+ byte[] bytes = memoryStream.ToArray();
+ return Convert.ToBase64String(bytes);
+ }
+
public async Task RefreshStatuses() => await GetStatuses(forceRefresh: true);
public async Task RefreshPics() => await GetPics(forceRefresh: true);
}
diff --git a/RestService.cs b/RestService.cs
index c0a9991..a5a8d35 100644
--- a/RestService.cs
+++ b/RestService.cs
@@ -132,6 +132,16 @@ namespace Neighbourhood.omg.lol {
return await PutPic(address, bytes);
}
+ public async Task PutPic(string address, FileResult file) {
+ byte[] bytes;
+ using var memoryStream = new MemoryStream();
+ using var fileStream = await file.OpenReadAsync();
+ await fileStream.CopyToAsync(memoryStream);
+ bytes = memoryStream.ToArray();
+
+ return await PutPic(address, bytes);
+ }
+
public async Task PutPic(string address, byte[] bytes) =>
await PutPic(address, Convert.ToBase64String(bytes));
diff --git a/wwwroot/css/style.css b/wwwroot/css/style.css
index f90da68..8566cb6 100644
--- a/wwwroot/css/style.css
+++ b/wwwroot/css/style.css
@@ -197,4 +197,37 @@ article.ephemeral {
.tabs a {
text-decoration:none;
+}
+
+.card-grid{
+ display: flex;
+ flex-direction:row;
+ flex-wrap:wrap;
+ gap: .5rem;
+}
+
+#pics article {
+ margin: 1rem auto;
+ text-align:center;
+}
+
+#pics article>:not(:first-child) {
+ text-align: left;
+}
+
+#pics article nav {
+ flex-wrap: wrap;
+}
+
+#pics.card-grid article{
+ max-width: 24rem;
+}
+@media only screen and (max-width: 895px) {
+ #pics.card-grid article {
+ max-width: calc(100% - 1rem);
+ }
+}
+
+#pics article > img:first-child {
+ text-align: center;
}
\ No newline at end of file