sync code

This commit is contained in:
2023-06-26 22:33:44 +08:00
parent 2d87e50dd0
commit 4bf330f824
26 changed files with 2644 additions and 62 deletions

View File

@@ -5,6 +5,8 @@ public sealed class Constants
public const string CategoryOther = "other";
public const string EventUnknown = "unknown";
public const string BaseUrl = "https://flower.tsanie.org";
public const SQLite.SQLiteOpenFlags Flags =
SQLite.SQLiteOpenFlags.ReadWrite |
SQLite.SQLiteOpenFlags.Create |

View File

@@ -26,12 +26,12 @@ public class FlowerDatabase
#if DEBUG
var result =
#endif
await database.CreateTablesAsync<FlowerItem, RecordItem>();
await database.CreateTablesAsync<FlowerItem, RecordItem, PhotoItem>();
#if DEBUG
foreach (var item in result.Results)
{
logger.LogDebug("create table {table}, result: {result}", item.Key, item.Value);
logger.LogInformation("create table {table}, result: {result}", item.Key, item.Value);
}
#endif
}

View File

@@ -18,11 +18,11 @@ public class FlowerItem
{
if (categoryName == null)
{
if (!Constants.Categories.TryGetValue(CategoryId, out categoryName))
if (!Constants.Categories.TryGetValue(CategoryId, out var name))
{
categoryName = Constants.CategoryOther;
name = Constants.CategoryOther;
}
// TODO: i18n
categoryName = LocalizationResource.GetText(name);
}
return categoryName;
}
@@ -40,6 +40,6 @@ public class FlowerItem
[Column("purchase")]
public string Purchase { get; set; }
[Column("photo")]
public byte[] Photo { get; set; }
[Column("memo")]
public string Memo { get; set; }
}

View File

@@ -0,0 +1,28 @@
using SQLite;
namespace Blahblah.FlowerStory.Data.Model;
[Table("photos")]
public class PhotoItem
{
[Column("pid"), PrimaryKey, AutoIncrement]
public int Id { get; set; }
[Column("fid")]
public int FlowerId { get; set; }
[Column("rid")]
public int RecordId { get; set; }
[Column("filetype")]
public string FileType { get; set; }
[Column("filename")]
public string FileName { get; set; }
[Column("path")]
public string Path { get; set; }
[Column("dateupload")]
public DateTimeOffset DateUpload { get; set; }
}

View File

@@ -8,6 +8,9 @@ public class RecordItem
[Column("rid"), PrimaryKey, AutoIncrement]
public int Id { get; set; }
[Column("fid")]
public int FlowerId { get; set; }
[Column("eid")]
public int EventId { get; set; }
@@ -18,15 +21,16 @@ public class RecordItem
{
if (eventName == null)
{
string evtkey;
if (Constants.Events.TryGetValue(EventId, out var @event))
{
eventName = @event.Name;
evtkey = @event.Name;
}
else
{
eventName = Constants.EventUnknown;
evtkey = Constants.EventUnknown;
}
// TODO: i18n
eventName = LocalizationResource.GetText(evtkey);
}
return eventName;
}
@@ -41,6 +45,6 @@ public class RecordItem
[Column("byname")]
public string ByUserName { get; set; }
[Column("photo")]
public byte[] Photo { get; set; }
[Column("memo")]
public string Memo { get; set; }
}

View File

@@ -2,10 +2,19 @@
public class UserItem
{
public string Id { get; set; }
public int Id { get; set; }
public string UserId { get; set; }
public int Level { get; set; }
public DateTimeOffset RegisterDate { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public byte[] Avatar { get; set; }
}

36
App/Extensions.cs Normal file
View File

@@ -0,0 +1,36 @@
using Microsoft.Extensions.Localization;
using System.Text;
namespace Blahblah.FlowerStory;
[ContentProperty(nameof(Key))]
public class LocalizeExtension : IMarkupExtension
{
//private IStringLocalizer<Localizations> Localizer { get; }
public string Key { get; set; }
//public LocalizeExtension()
//{
// Localizer = MauiApplication.Current.Services.GetService<IStringLocalizer<Localizations>>();
//}
public object ProvideValue(IServiceProvider _)
{
return LocalizationResource.Localizer.GetString(Key);
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider);
}
sealed class LocalizationResource
{
private static IStringLocalizer<Localizations> localizer;
public static IStringLocalizer<Localizations> Localizer => localizer ??= MauiApplication.Current.Services.GetService<IStringLocalizer<Localizations>>();
public static string GetText(string key)
{
return Localizer.GetString(key);
}
}

View File

@@ -70,8 +70,26 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Localization" Version="7.0.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
<PackageReference Include="Microsoft.Maui.Graphics.Skia" Version="7.0.86" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.3" />
<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.4" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.5" />
</ItemGroup>
<ItemGroup>
<Compile Update="Localizations.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Localizations.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Localizations.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Localizations.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

72
App/Localizations.Designer.cs generated Normal file
View File

@@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Blahblah.FlowerStory {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Localizations {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Localizations() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Blahblah.FlowerStory.Localizations", typeof(Localizations).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Unknown.
/// </summary>
internal static string unknown {
get {
return ResourceManager.GetString("unknown", resourceCulture);
}
}
}
}

123
App/Localizations.resx Normal file
View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="unknown" xml:space="preserve">
<value>Unknown</value>
</data>
</root>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="unknown" xml:space="preserve">
<value>未知</value>
</data>
</root>

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:l="clr-namespace:Blahblah.FlowerStory"
xmlns:forms="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
x:Class="Blahblah.FlowerStory.MainPage">
<ScrollView>
@@ -15,8 +17,10 @@
HeightRequest="200"
HorizontalOptions="Center" />
<forms:SKCanvasView x:Name="canvasView" PaintSurface="canvasView_PaintSurface"/>
<Label
Text="Hello, World!"
Text="{l:Localize unknown}"
SemanticProperties.HeadingLevel="Level1"
FontSize="32"
HorizontalOptions="Center" />

View File

@@ -46,5 +46,10 @@ namespace Blahblah.FlowerStory
}
});
}
private void canvasView_PaintSurface(object sender, SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs e)
{
}
}
}

View File

@@ -28,6 +28,8 @@ namespace Blahblah.FlowerStory
builder.Services.AddSingleton<MainPage>();
builder.Services.AddSingleton<FlowerDatabase>();
builder.Services.AddLocalization();
return builder.Build();
}
}