home page for App

This commit is contained in:
2023-07-27 22:07:24 +08:00
parent 02ac33fc07
commit befbc7fc9b
40 changed files with 1175 additions and 398 deletions

View File

@ -1,19 +1,76 @@
using SQLite;
using Microsoft.Extensions.Logging;
using SQLite;
namespace Blahblah.FlowerApp.Data;
public sealed class Constants
internal sealed class Constants
{
public const string CategoryOther = "other";
public const string EventUnknown = "unknown";
public const string BaseUrl = "https://flower.tsanie.org";
public const string ApiVersionName = "api_version";
public const string LastTokenName = "last_token";
public const string BaseUrl = "https://app.blahblaho.com";
public const SQLiteOpenFlags SQLiteFlags =
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache;
private const string dbFilename = "flowerstory.db3";
const string dbFilename = "flowerstory.db3";
public static string DatabasePath => Path.Combine(FileSystem.AppDataDirectory, dbFilename);
static string? apiVersion;
public static string? ApiVersion => apiVersion;
static string? authorization;
public static string? Authorization => authorization;
public static void SetAuthorization(string auth)
{
authorization = auth;
}
public static async Task<Definitions?> Initialize(ILogger logger, string? version, CancellationToken cancellation = default)
{
try
{
var v = await Extensions.FetchAsync<string>("api/version", cancellation);
apiVersion = v;
if (v != version)
{
var definition = await Extensions.FetchAsync<Definitions>($"api/consts?{v}", cancellation);
return definition;
}
}
catch (Exception ex)
{
logger.LogError("error occurs on fetching version and definitions, {error}", ex);
}
return null;
}
}
internal record Definitions
{
public required string ApiVersion { get; init; }
public required Dictionary<int, NamedItem> Categories { get; init; }
public required Dictionary<int, EventItem> Events { get; init; }
}
internal record NamedItem(string Name, string? Description)
{
public string Name { get; init; } = Name;
public string? Description { get; init; } = Description;
}
internal record EventItem(string Name, string? Description, bool Unique) : NamedItem(Name, Description)
{
public bool Unique { get; init; } = Unique;
}

View File

@ -13,6 +13,130 @@ public class FlowerDatabase
public FlowerDatabase(ILogger<FlowerDatabase> logger)
{
this.logger = logger;
Task.Run(async () =>
{
try
{
await Setup();
}
catch (Exception ex)
{
logger.LogError("error occurs on setup, {error}", ex);
}
});
}
private Dictionary<int, NamedItem>? categories;
private Dictionary<int, EventItem>? events;
public string Category(int categoryId)
{
if (categories?.TryGetValue(categoryId, out var category) == true)
{
return category.Name;
}
return Constants.CategoryOther;
}
public string Event(int eventId)
{
if (events?.TryGetValue(eventId, out var @event) == true)
{
return @event.Name;
}
return Constants.EventUnknown;
}
private async Task Setup()
{
await Init();
#if DEBUG
Constants.SetAuthorization("RF4mfoUur0vHtWzHwD42ka0FhIfGaPnBxoQgrXOYEDg=");
#else
var token = await database.Table<ParamItem>().FirstOrDefaultAsync(p => p.Code == Constants.LastTokenName);
if (token != null)
{
Constants.SetAuthorization(token.Value);
}
#endif
var version = await database.Table<ParamItem>().FirstOrDefaultAsync(p => p.Code == Constants.ApiVersionName);
var definition = await Constants.Initialize(logger, version?.Value);
if (definition != null)
{
categories = definition.Categories;
events = definition.Events;
logger.LogInformation("new version founded, from ({from}) to ({to})", version?.Value, definition.ApiVersion);
if (version == null)
{
version = new ParamItem
{
Code = Constants.ApiVersionName,
Value = definition.ApiVersion
};
}
else
{
version.Value = definition.ApiVersion;
}
await database.InsertOrReplaceAsync(version);
// replace local definitions
await database.DeleteAllAsync<DefinitionItem>();
var defs = new List<DefinitionItem>();
foreach (var category in definition.Categories)
{
defs.Add(new DefinitionItem
{
DefinitionType = 0,
DefinitionId = category.Key,
Name = category.Value.Name,
Description = category.Value.Description
});
}
foreach (var @event in definition.Events)
{
defs.Add(new DefinitionItem
{
DefinitionType = 1,
DefinitionId = @event.Key,
Name = @event.Value.Name,
Description = @event.Value.Description,
Unique = @event.Value.Unique
});
}
var rows = await database.InsertAllAsync(defs);
logger.LogInformation("{count} definitions, {rows} rows inserted", defs.Count, rows);
}
else
{
// use local definitions
var defs = await database.Table<DefinitionItem>().ToListAsync();
var cates = new Dictionary<int, NamedItem>();
var evts = new Dictionary<int, EventItem>();
foreach (var d in defs)
{
if (d.DefinitionType == 0)
{
// category
cates[d.DefinitionId] = new NamedItem(d.Name, d.Description);
}
else if (d.DefinitionType == 1)
{
// event
evts[d.DefinitionId] = new EventItem(d.Name, d.Description, d.Unique ?? false);
}
}
categories = cates;
events = evts;
}
}
private async Task Init()
@ -27,7 +151,13 @@ public class FlowerDatabase
#if DEBUG
var result =
#endif
await database.CreateTablesAsync<FlowerItem, RecordItem, PhotoItem, UserItem>();
await database.CreateTablesAsync(CreateFlags.None,
typeof(FlowerItem),
typeof(RecordItem),
typeof(PhotoItem),
typeof(UserItem),
typeof(DefinitionItem),
typeof(ParamItem));
#if DEBUG
foreach (var item in result.Results)

View File

@ -0,0 +1,29 @@
using SQLite;
namespace Blahblah.FlowerApp.Data.Model;
[Table("definitions")]
public class DefinitionItem
{
[Column("did"), PrimaryKey, AutoIncrement]
public int Id { get; set; }
/// <summary>
/// - 0: category
/// - 1: event
/// </summary>
[Column("type"), NotNull]
public int DefinitionType { get; set; }
[Column("id"), NotNull]
public int DefinitionId { get; set; }
[Column("name"), NotNull]
public string Name { get; set; } = null!;
[Column("description")]
public string? Description { get; set; }
[Column("unique")]
public bool? Unique { get; set; }
}

View File

@ -20,8 +20,6 @@ public class FlowerItem
[Column("datebuy"), NotNull]
public long DateBuyUnixTime { get; set; }
public DateTimeOffset DateBuy => DateTimeOffset.FromUnixTimeMilliseconds(DateBuyUnixTime);
[Column("cost")]
public decimal? Cost { get; set; }
@ -37,5 +35,9 @@ public class FlowerItem
[Column("longitude")]
public double? Longitude { get; set; }
[Ignore]
public PhotoItem[]? Photos { get; set; }
[Ignore]
public int? Distance { get; set; }
}

View File

@ -0,0 +1,22 @@
using SQLite;
namespace Blahblah.FlowerApp.Data.Model;
[Table("params")]
public class ParamItem
{
[Column("pid"), PrimaryKey, AutoIncrement]
public int Id { get; set; }
[Column("uid")]
public int? OwnerId { get; set; }
[Column("code"), NotNull]
public string Code { get; set; } = null!;
[Column("value"), NotNull]
public string Value { get; set; } = null!;
[Column("description")]
public string? Description { get; set; }
}

View File

@ -29,8 +29,12 @@ public class PhotoItem
[Column("dateupload"), NotNull]
public long DateUploadUnixTime { get; set; }
public DateTimeOffset DateUpload => DateTimeOffset.FromUnixTimeMilliseconds(DateUploadUnixTime);
[Column("url")]
public string Url { get; set; } = null!;
[Column("width")]
public int? Width { get; set; }
[Column("height")]
public int? Height { get; set; }
}

View File

@ -19,8 +19,6 @@ public class RecordItem
[Column("date"), NotNull]
public long DateUnixTime { get; set; }
public DateTimeOffset Date => DateTimeOffset.FromUnixTimeMilliseconds(DateUnixTime);
[Column("byuid")]
public int? ByUserId { get; set; }

View File

@ -4,15 +4,15 @@ namespace Blahblah.FlowerApp.Data.Model;
public class UserItem
{
[Column("uid"), PrimaryKey, AutoIncrement]
[Column("uid"), PrimaryKey, NotNull]
public int Id { get; set; }
[Column("token"), Indexed, NotNull]
public string Token { get; set; } = null!;
[Column("id"), NotNull]
public string UserId { get; set; } = null!;
[Column("token"), NotNull]
public string Token { get; set; } = null!;
[Column("name"), NotNull]
public string Name { get; set; } = null!;
@ -22,8 +22,6 @@ public class UserItem
[Column("regdate"), NotNull]
public long RegisterDateUnixTime { get; set; }
public DateTimeOffset RegisterDate => DateTimeOffset.FromUnixTimeMilliseconds(RegisterDateUnixTime);
//[Column("activedate")]
//public long? ActiveDateUnixTime { get; set; }