utilities feature
This commit is contained in:
100
Gallery.Share/Resources/Helper.cs
Normal file
100
Gallery.Share/Resources/Helper.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using Gallery.Util;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace Gallery.Resources
|
||||
{
|
||||
public class Helper
|
||||
{
|
||||
private static readonly Dictionary<string, LanguageResource> dict = new();
|
||||
|
||||
public static string GetResource(string name, params object[] args)
|
||||
{
|
||||
if (!dict.TryGetValue(App.CurrentCulture.PlatformString, out LanguageResource lang))
|
||||
{
|
||||
lang = new LanguageResource(App.CurrentCulture);
|
||||
dict.Add(App.CurrentCulture.PlatformString, lang);
|
||||
}
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
return lang[name];
|
||||
}
|
||||
return string.Format(lang[name], args);
|
||||
}
|
||||
|
||||
private class LanguageResource
|
||||
{
|
||||
private readonly Dictionary<string, string> strings;
|
||||
|
||||
public string this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (strings != null && strings.TryGetValue(key, out string val))
|
||||
{
|
||||
return val;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public LanguageResource(PlatformCulture lang)
|
||||
{
|
||||
try
|
||||
{
|
||||
const string PROJECT = "Gallery";
|
||||
const string PLATFORM =
|
||||
#if __IOS__
|
||||
"iOS";
|
||||
#elif __ANDROID__
|
||||
"Droid";
|
||||
#endif
|
||||
var langId = $"{PROJECT}.{PLATFORM}.Resources.Languages.{lang.Language}.xml";
|
||||
var langCodeId = $"{PROJECT}.{PLATFORM}.Resources.Languages.{lang.LanguageCode}.xml";
|
||||
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LanguageResource)).Assembly;
|
||||
var names = assembly.GetManifestResourceNames();
|
||||
var name = names.FirstOrDefault(n =>
|
||||
string.Equals(n, langId, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(n, langCodeId, StringComparison.OrdinalIgnoreCase));
|
||||
if (name == null)
|
||||
{
|
||||
name = $"{PROJECT}.{PLATFORM}.Resources.Languages.zh-CN.xml";
|
||||
}
|
||||
var xml = new XmlDocument();
|
||||
using (var stream = assembly.GetManifestResourceStream(name))
|
||||
{
|
||||
xml.Load(stream);
|
||||
}
|
||||
strings = new Dictionary<string, string>();
|
||||
foreach (XmlElement ele in xml.DocumentElement)
|
||||
{
|
||||
strings[ele.Name] = ele.InnerText;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// load failed
|
||||
Log.Error("language.ctor", $"failed to load xml resource: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TextExtension : IMarkupExtension
|
||||
{
|
||||
public string Text { get; set; }
|
||||
|
||||
public object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (Text == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
return Helper.GetResource(Text);
|
||||
}
|
||||
}
|
||||
}
|
4
Gallery.Share/Resources/Languages/zh-CN.xml
Normal file
4
Gallery.Share/Resources/Languages/zh-CN.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<root>
|
||||
<Title>Gallery</Title>
|
||||
</root>
|
36
Gallery.Share/Resources/PlatformCulture.cs
Normal file
36
Gallery.Share/Resources/PlatformCulture.cs
Normal file
@ -0,0 +1,36 @@
|
||||
namespace Gallery.Resources
|
||||
{
|
||||
public class PlatformCulture
|
||||
{
|
||||
public string PlatformString { get; private set; }
|
||||
public string LanguageCode { get; private set; }
|
||||
public string LocaleCode { get; private set; }
|
||||
|
||||
public string Language => string.IsNullOrEmpty(LocaleCode) ? LanguageCode : $"{LanguageCode}-{LocaleCode}";
|
||||
|
||||
public PlatformCulture() : this(null) { }
|
||||
public PlatformCulture(string cultureString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(cultureString))
|
||||
{
|
||||
cultureString = "zh-CN";
|
||||
}
|
||||
|
||||
PlatformString = cultureString.Replace('_', '-');
|
||||
var index = PlatformString.IndexOf('-');
|
||||
if (index > 0)
|
||||
{
|
||||
var parts = PlatformString.Split('-');
|
||||
LanguageCode = parts[0];
|
||||
LocaleCode = parts[^1];
|
||||
}
|
||||
else
|
||||
{
|
||||
LanguageCode = PlatformString;
|
||||
LocaleCode = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => PlatformString;
|
||||
}
|
||||
}
|
35
Gallery.Share/Resources/Theme/DarkTheme.cs
Normal file
35
Gallery.Share/Resources/Theme/DarkTheme.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Gallery.Services;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.Resources.Theme
|
||||
{
|
||||
public class DarkTheme : Theme
|
||||
{
|
||||
private static DarkTheme instance;
|
||||
public static DarkTheme Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new DarkTheme();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public DarkTheme()
|
||||
{
|
||||
InitColors();
|
||||
InitResources();
|
||||
}
|
||||
|
||||
private void InitColors()
|
||||
{
|
||||
Add(StatusBarStyle, StatusBarStyles.WhiteText);
|
||||
Add(NavigationColor, Color.FromRgb(0x11, 0x11, 0x11));
|
||||
|
||||
Add(Primary, Color.FromRgb(33, 150, 243));
|
||||
}
|
||||
}
|
||||
}
|
35
Gallery.Share/Resources/Theme/LightTheme.cs
Normal file
35
Gallery.Share/Resources/Theme/LightTheme.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Gallery.Services;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.Resources.Theme
|
||||
{
|
||||
public class LightTheme : Theme
|
||||
{
|
||||
private static LightTheme instance;
|
||||
public static LightTheme Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new LightTheme();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public LightTheme()
|
||||
{
|
||||
InitColors();
|
||||
InitResources();
|
||||
}
|
||||
|
||||
private void InitColors()
|
||||
{
|
||||
Add(StatusBarStyle, StatusBarStyles.DarkText);
|
||||
Add(NavigationColor, Color.FromRgb(0xf0, 0xf0, 0xf0));
|
||||
|
||||
Add(Primary, Color.FromRgb(33, 150, 243));
|
||||
}
|
||||
}
|
||||
}
|
44
Gallery.Share/Resources/Theme/Theme.cs
Normal file
44
Gallery.Share/Resources/Theme/Theme.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using Gallery.Resources.UI;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.Resources.Theme
|
||||
{
|
||||
public abstract class Theme : ResourceDictionary
|
||||
{
|
||||
public const string StatusBarStyle = nameof(StatusBarStyle);
|
||||
public const string NavigationColor = nameof(NavigationColor);
|
||||
|
||||
public const string IconLightFamily = nameof(IconLightFamily);
|
||||
public const string IconRegularFamily = nameof(IconRegularFamily);
|
||||
public const string IconSolidFamily = nameof(IconSolidFamily);
|
||||
public const string ScreenBottomPadding = nameof(ScreenBottomPadding);
|
||||
|
||||
public const string IconClose = nameof(IconClose);
|
||||
public const string FontIconRefresh = nameof(FontIconRefresh);
|
||||
|
||||
public const string Primary = nameof(Primary);
|
||||
|
||||
protected void InitResources()
|
||||
{
|
||||
Add(IconLightFamily, Definition.IconLightFamily);
|
||||
Add(IconRegularFamily, Definition.IconRegularFamily);
|
||||
Add(IconSolidFamily, Definition.IconSolidFamily);
|
||||
Add(ScreenBottomPadding, Definition.ScreenBottomPadding);
|
||||
|
||||
Add(FontIconRefresh, GetFontIcon(Definition.IconRefresh, Definition.IconSolidFamily));
|
||||
|
||||
Add(IconClose, Definition.IconClose);
|
||||
}
|
||||
|
||||
private FontImageSource GetFontIcon(string icon, string family, Color color = default)
|
||||
{
|
||||
return new FontImageSource
|
||||
{
|
||||
FontFamily = family,
|
||||
Glyph = icon,
|
||||
Size = Definition.FontSizeTitle,
|
||||
Color = color
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
129
Gallery.Share/Resources/UI/Definition.cs
Normal file
129
Gallery.Share/Resources/UI/Definition.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using Gallery.Util;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Gallery.Resources.UI
|
||||
{
|
||||
public static class Definition
|
||||
{
|
||||
public const double FontSizeTitle = 18.0;
|
||||
|
||||
public static readonly Thickness ScreenBottomPadding;
|
||||
|
||||
#if __IOS__
|
||||
public const string IconLightFamily = "FontAwesome5Pro-Light";
|
||||
public const string IconRegularFamily = "FontAwesome5Pro-Regular";
|
||||
public const string IconSolidFamily = "FontAwesome5Pro-Solid";
|
||||
|
||||
public const string IconLeft = "\uf104";
|
||||
#elif __ANDROID__
|
||||
public const string IconLightFamily = "fa-light-300.ttf#FontAwesome5Pro-Light";
|
||||
public const string IconRegularFamily = "fa-regular-400.ttf#FontAwesome5Pro-Regular";
|
||||
public const string IconSolidFamily = "fa-solid-900.ttf#FontAwesome5Pro-Solid";
|
||||
|
||||
public const string IconLeft = "\uf053";
|
||||
#endif
|
||||
|
||||
public const string IconRefresh = "\uf2f9";
|
||||
public const string IconClose = "\uf057";
|
||||
|
||||
static Definition()
|
||||
{
|
||||
_ = IsFullscreenDevice;
|
||||
if (_isBottomPadding)
|
||||
{
|
||||
if (DeviceInfo.Idiom == DeviceIdiom.Phone)
|
||||
{
|
||||
ScreenBottomPadding = new Thickness(0, 0, 0, 26);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenBottomPadding = new Thickness(0, 0, 0, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _isBottomPadding;
|
||||
private static bool? _isFullscreenDevice;
|
||||
public static bool IsFullscreenDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_isFullscreenDevice != null)
|
||||
{
|
||||
return _isFullscreenDevice.Value;
|
||||
}
|
||||
#if __IOS__
|
||||
try
|
||||
{
|
||||
var model = DeviceInfo.Model;
|
||||
if (model == "iPhone10,3")
|
||||
{
|
||||
// iPhone X
|
||||
_isFullscreenDevice = true;
|
||||
_isBottomPadding = true;
|
||||
}
|
||||
else if (model.StartsWith("iPhone"))
|
||||
{
|
||||
var vs = model[6..].Split(',');
|
||||
if (vs.Length == 2 && int.TryParse(vs[0], out int main) && int.TryParse(vs[1], out int sub))
|
||||
{
|
||||
// iPhone X
|
||||
// iPhone XS/XR/11/12 or newer
|
||||
var flag = (main == 10 && sub == 6) || main > 10;
|
||||
_isFullscreenDevice = flag;
|
||||
_isBottomPadding = flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isFullscreenDevice = false;
|
||||
}
|
||||
}
|
||||
else if (model.StartsWith("iPad"))
|
||||
{
|
||||
var vs = model[4..].Split(',');
|
||||
if (vs.Length == 2 && int.TryParse(vs[0], out int main) && int.TryParse(vs[1], out int sub))
|
||||
{
|
||||
// iPad Pro 11-inch (gen 1~3)
|
||||
// iPad Pro 12.9-inch (gen 3~5)
|
||||
var flag = main == 8 || (main == 13 && sub >= 4 && sub < 12);
|
||||
_isBottomPadding = flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isFullscreenDevice = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG
|
||||
// simulator
|
||||
var name = DeviceInfo.Name;
|
||||
var flag =
|
||||
name.StartsWith("iPhone X") ||
|
||||
name.StartsWith("iPhone 11") ||
|
||||
name.StartsWith("iPhone 12");
|
||||
_isFullscreenDevice = flag;
|
||||
_isBottomPadding = flag ||
|
||||
name.StartsWith("iPad Pro (11-inch)") ||
|
||||
name.StartsWith("iPad Pro (12.9-inch) (3rd generation)") ||
|
||||
name.StartsWith("iPad Pro (12.9-inch) (4th generation)") ||
|
||||
name.StartsWith("iPad Pro (12.9-inch) (5th generation)");
|
||||
#else
|
||||
_isFullscreenDevice = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("device.model.get", $"failed to get the device model. {ex.Message}");
|
||||
}
|
||||
#else
|
||||
_isFullscreenDevice = false;
|
||||
#endif
|
||||
return _isFullscreenDevice.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user