using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web.Virtualization; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace Neighbourhood.omg.lol.Models { public class State { public Page CurrentPage { get; set; } public AccountResponseData? AccountInfo { get; set; } public AddressResponseList? AddressList { get; set; } public string? Name { get => AccountInfo?.Name; } public string? Email { get => AccountInfo?.Email; } public IEnumerable? AddressNames { get => AddressList?.Select(a => a.Address); } public AddressResponseData? SelectedAddress { get; set; } public string? SelectedAddressName { get => SelectedAddress?.Address; } public List? Statuses { get; set; } public List? Pics { get; set; } public List? NowGarden { get; set; } public List? CachedAddressStatuses { get; set; } public List? CachedAddressPics { get; set; } public MarkupString? CachedAddressBio { get; set; } private string? _cachedAddress; public string? CachedAddress { get => _cachedAddress; set { if (_cachedAddress != value) { _cachedAddress = value; CachedAddressStatuses = new List(); CachedAddressPics = new List(); CachedAddressBio = null; } } } public async Task PopulateAccountDetails(string token) { RestService api = new RestService(token); string accountJson = Preferences.Default.Get("accountdetails", string.Empty); string addressJson = Preferences.Default.Get("accountaddresses", string.Empty); string selectedAddressJson = Preferences.Default.Get("selectedaddress", string.Empty); if (!string.IsNullOrEmpty(accountJson)) AccountInfo = JsonSerializer.Deserialize(accountJson); if (!string.IsNullOrEmpty(addressJson)) AddressList = JsonSerializer.Deserialize(addressJson); if (!string.IsNullOrEmpty(selectedAddressJson)) SelectedAddress = JsonSerializer.Deserialize(selectedAddressJson); // if we haven't got account info, attempt to retrieve it. if (AccountInfo == null) { AccountInfo = await api.AccountInfo(); if (AccountInfo != null) { Preferences.Default.Set("accountdetails", JsonSerializer.Serialize(AccountInfo)); } } // if we don't have the list of addresses, attempt to retrieve that. if (AddressList == null) { AddressList = await api.Addresses(); if (AddressList != null) { Preferences.Default.Set("accountaddresses", JsonSerializer.Serialize(AddressList)); SelectedAddress = AddressList.FirstOrDefault(); Preferences.Default.Set("selectedaddress", JsonSerializer.Serialize(SelectedAddress)); } } } public async Task RemoveAccountDetails() { Preferences.Default.Clear(); AccountInfo = null; AddressList = null; SelectedAddress = null; } public async Task GetBio(string address, bool forceRefresh = false) { CachedAddress = address; if (forceRefresh || CachedAddressBio == null) { RestService api = new RestService(); CachedAddressBio = await api.StatuslogBio(address); } return CachedAddressBio; } public async Task?> GetStatuses(bool forceRefresh = false) { RestService api = new RestService(); if (forceRefresh || this.Statuses == null || this.Statuses.Count == 0) { this.Statuses = await api.StatuslogLatest(); } return this.Statuses; } public async ValueTask> VirtualStatuses(ItemsProviderRequest request) { // TODO: request.cancellationToken var statuses = (await this.GetStatuses()) ?? new List(); var numStatuses = Math.Min(request.Count, statuses.Count - request.StartIndex); return new ItemsProviderResult(statuses.Skip(request.StartIndex).Take(numStatuses), statuses.Count); } public async ValueTask> VirtualStatuses(ItemsProviderRequest request, string address) { // TODO: request.cancellationToken RestService api = new RestService(); CachedAddressStatuses = (await api.Statuslog(address)) ?? new List(); var numStatuses = Math.Min(request.Count, CachedAddressStatuses.Count - request.StartIndex); return new ItemsProviderResult(CachedAddressStatuses.Skip(request.StartIndex).Take(numStatuses), CachedAddressStatuses.Count); } public Func>> VirtualStatusesFunc(string? address = null) { if (address == null) return VirtualStatuses; else { CachedAddress = address; return async (ItemsProviderRequest request) => await VirtualStatuses(request, CachedAddress); } } public async Task?> GetNowGarden(bool forceRefresh = false) { RestService api = new RestService(); if (forceRefresh || this.NowGarden == null || this.NowGarden.Count == 0) { this.NowGarden = await api.NowGarden(); } return this.NowGarden; } public async ValueTask> VirtualNowGarden(ItemsProviderRequest request) { // TODO: request.cancellationToken var garden = (await this.GetNowGarden()) ?? new List(); var numSeedlings = Math.Min(request.Count, garden.Count - request.StartIndex); return new ItemsProviderResult(garden.Skip(request.StartIndex).Take(numSeedlings), garden.Count); } public Func>> VirtualNowGardenFunc() { return VirtualNowGarden; } public async Task?> GetPics(bool forceRefresh = false) { if(forceRefresh || this.Pics == null || this.Pics.Count == 0) { RestService api = new RestService(); this.Pics = await api.SomePics(); } return this.Pics; } public async Task?> GetPics(string address, bool forceRefresh = false) { CachedAddress = address; if (forceRefresh || this.Pics == null || this.Pics.Count == 0) { RestService api = new RestService(); CachedAddressPics = (await api.SomePics(address)) ?? new List(); } return CachedAddressPics; } public async ValueTask> VirtualPics(ItemsProviderRequest request) { // TODO: request.cancellationToken var pics = (await this.GetPics()) ?? new List(); var numPics = Math.Min(request.Count, pics.Count - request.StartIndex); return new ItemsProviderResult(pics.Skip(request.StartIndex).Take(numPics), pics.Count); } public async ValueTask> VirtualPics(ItemsProviderRequest request, string address) { // TODO: request.cancellationToken RestService api = new RestService(); CachedAddressPics = (await api.SomePics(address)) ?? new List(); var numPics = Math.Min(request.Count, CachedAddressPics.Count - request.StartIndex); return new ItemsProviderResult(CachedAddressPics.Skip(request.StartIndex).Take(numPics), CachedAddressPics.Count); } public Func>> VirtualPicsFunc(string? address = null) { if (address == null) return VirtualPics; else { CachedAddress = address; return async (ItemsProviderRequest request) => await VirtualPics(request, CachedAddress); } } 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); public async Task RefreshNow() => await GetNowGarden(forceRefresh: true); public static string RelativeTimeFromUnix(long unix) { DateTimeOffset createdTime = DateTimeOffset.UnixEpoch.AddSeconds(unix); TimeSpan offset = DateTimeOffset.UtcNow - createdTime; var offsetString = string.Empty; if (offset.TotalDays >= 1) offsetString = $"{Math.Floor(offset.TotalDays)} days ago"; else if (offset.TotalHours >= 1) offsetString = $"{Math.Floor(offset.TotalHours)} hours, {offset.Minutes} minutes ago"; else if (offset.TotalMinutes >= 1) offsetString = $"{Math.Floor(offset.TotalMinutes)} minutes ago"; else offsetString = $"{Math.Floor(offset.TotalSeconds)} seconds ago"; return offsetString; } } public enum Page { None = 0, Status, Pics, Ephemeral, Person, Other } }