diff --git a/README.md b/README.md
index 1740102..6f071cf 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
-# UniScan
+
+
+
UniScan


----
+
Modular scanner/radio client and multi-broadcast server. Plug in a scanner, set it up in the server software, and open
it up to the internet for others to listen to, and control it yourself by logging into an admin user.
@@ -27,8 +29,12 @@ it up to the internet for others to listen to, and control it yourself by loggin
| [UniScan.UserInterface](src/Core/UniScan.UserInterface) | 0.0.1 | Serverside UI definitions |
| [UniScan.Client.Core](src/Client/UniScan.Client.Core) | 0.3.0 | Holds shared client code, no dep on Avalonia |
| [UniScan.Client.App](src/Client/UniScan.Client.App) | 0.1.1 | UniScan client |
-| [UniScan.Client.App.Platform.Android](src/Client/UniScan.Client.App.Platform.Android) | 0.0.5 | UniScan client for Android |
-| [UniScan.Client.App.Platform.Browser](src/Client/UniScan.Client.App.Platform.Browser) | 0.1.3 | UniScan client for web browsers (https://uniscan.dexrn.me) |
+| [UniScan.Client.App.Platform.Android](src/Client/UniScan.Client.App.Platform.Android) | 0.0.6 | UniScan client for Android |
+| [UniScan.Client.App.Platform.Browser](src/Client/UniScan.Client.App.Platform.Browser) | 0.1.4 | UniScan client for web browsers (https://uniscan.dexrn.me) |
| [UniScan.Client.App.Platform.Desktop](src/Client/UniScan.Client.App.Platform.Desktop) | 0.0.3 | UniScan client for desktop |
| [UniScan.Client.App.Platform.iOS](src/Client/UniScan.Client.App.Platform.iOS) | 0.0.1 | UniScan client for iOS |
-| [UniScan.Modules.DebugModule](src/Modules/UniScan.Modules.DebugModule) | 0.0.1 | |
\ No newline at end of file
+| [UniScan.Modules.DebugModule](src/Modules/UniScan.Modules.DebugModule) | 0.0.1 | |
+
+## Credits
+(in the future, these will be included in the About page.)
+- [Unobtainable Melon (Unomelon)](https://bsky.app/profile/unomelon.bsky.social) | Creating the base of the logo for me to work off of. (thus helping me learn a little about pixel art in the process)
\ No newline at end of file
diff --git a/branding/desktop/pixel/README.md b/branding/desktop/pixel/README.md
new file mode 100644
index 0000000..7a055ff
--- /dev/null
+++ b/branding/desktop/pixel/README.md
@@ -0,0 +1,5 @@
+Thanks to [Unobtainable Melon (Unomelon)](https://bsky.app/profile/unomelon.bsky.social) for drawing the bases of the logos for me to work off of to make the final product!
+
+There is also a handheld version that will be added when logo switching is added.
+
+In the future, the displays on the devices will be colorable as a setting. (kind of like how the BCD996P2 does it)
\ No newline at end of file
diff --git a/branding/desktop/pixel/alpha/logo.alpha.1024x1024.png b/branding/desktop/pixel/alpha/logo.alpha.1024x1024.png
new file mode 100644
index 0000000..b969205
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.1024x1024.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.128x128.png b/branding/desktop/pixel/alpha/logo.alpha.128x128.png
new file mode 100644
index 0000000..afc537e
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.128x128.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.192x192.png b/branding/desktop/pixel/alpha/logo.alpha.192x192.png
new file mode 100644
index 0000000..3bfd5bd
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.192x192.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.256x256.png b/branding/desktop/pixel/alpha/logo.alpha.256x256.png
new file mode 100644
index 0000000..59d4eac
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.256x256.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.32x32.png b/branding/desktop/pixel/alpha/logo.alpha.32x32.png
new file mode 100644
index 0000000..3c905ba
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.32x32.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.512x512.png b/branding/desktop/pixel/alpha/logo.alpha.512x512.png
new file mode 100644
index 0000000..eac086a
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.512x512.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.64x64.png b/branding/desktop/pixel/alpha/logo.alpha.64x64.png
new file mode 100644
index 0000000..1637879
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.64x64.png differ
diff --git a/branding/desktop/pixel/alpha/logo.alpha.96x96.png b/branding/desktop/pixel/alpha/logo.alpha.96x96.png
new file mode 100644
index 0000000..7bf9ed5
Binary files /dev/null and b/branding/desktop/pixel/alpha/logo.alpha.96x96.png differ
diff --git a/branding/desktop/pixel/logo.1024x1024.png b/branding/desktop/pixel/logo.1024x1024.png
new file mode 100644
index 0000000..d2f0e04
Binary files /dev/null and b/branding/desktop/pixel/logo.1024x1024.png differ
diff --git a/branding/desktop/pixel/logo.128x128.png b/branding/desktop/pixel/logo.128x128.png
new file mode 100644
index 0000000..bdeed9c
Binary files /dev/null and b/branding/desktop/pixel/logo.128x128.png differ
diff --git a/branding/desktop/pixel/logo.192x192.png b/branding/desktop/pixel/logo.192x192.png
new file mode 100644
index 0000000..c19071e
Binary files /dev/null and b/branding/desktop/pixel/logo.192x192.png differ
diff --git a/branding/desktop/pixel/logo.256x256.png b/branding/desktop/pixel/logo.256x256.png
new file mode 100644
index 0000000..92d4a27
Binary files /dev/null and b/branding/desktop/pixel/logo.256x256.png differ
diff --git a/branding/desktop/pixel/logo.32x32.png b/branding/desktop/pixel/logo.32x32.png
new file mode 100644
index 0000000..8a2ee01
Binary files /dev/null and b/branding/desktop/pixel/logo.32x32.png differ
diff --git a/branding/desktop/pixel/logo.512x512.png b/branding/desktop/pixel/logo.512x512.png
new file mode 100644
index 0000000..7dff1be
Binary files /dev/null and b/branding/desktop/pixel/logo.512x512.png differ
diff --git a/branding/desktop/pixel/logo.64x64.png b/branding/desktop/pixel/logo.64x64.png
new file mode 100644
index 0000000..2fc0394
Binary files /dev/null and b/branding/desktop/pixel/logo.64x64.png differ
diff --git a/branding/desktop/pixel/logo.96x96.png b/branding/desktop/pixel/logo.96x96.png
new file mode 100644
index 0000000..87723a1
Binary files /dev/null and b/branding/desktop/pixel/logo.96x96.png differ
diff --git a/branding/desktop/pixel/logo.ico b/branding/desktop/pixel/logo.ico
new file mode 100644
index 0000000..9069329
Binary files /dev/null and b/branding/desktop/pixel/logo.ico differ
diff --git a/branding/desktop/pixel/logo.svg b/branding/desktop/pixel/logo.svg
new file mode 100644
index 0000000..df342ed
--- /dev/null
+++ b/branding/desktop/pixel/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.1024x1024.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.1024x1024.png
new file mode 100644
index 0000000..a4fcc11
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.1024x1024.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.128x128.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.128x128.png
new file mode 100644
index 0000000..43d3ae4
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.128x128.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.192x192.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.192x192.png
new file mode 100644
index 0000000..9015b78
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.192x192.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.256x256.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.256x256.png
new file mode 100644
index 0000000..8e99043
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.256x256.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.32x32.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.32x32.png
new file mode 100644
index 0000000..8c5f645
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.32x32.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.512x512.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.512x512.png
new file mode 100644
index 0000000..0044edc
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.512x512.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.64x64.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.64x64.png
new file mode 100644
index 0000000..d8fc32b
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.64x64.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.96x96.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.96x96.png
new file mode 100644
index 0000000..566dc9b
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.96x96.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.1024x1024.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.1024x1024.png
new file mode 100644
index 0000000..a2678c6
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.1024x1024.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.128x128.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.128x128.png
new file mode 100644
index 0000000..b523f13
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.128x128.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.192x192.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.192x192.png
new file mode 100644
index 0000000..6677dbc
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.192x192.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.256x256.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.256x256.png
new file mode 100644
index 0000000..535ed46
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.256x256.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.32x32.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.32x32.png
new file mode 100644
index 0000000..51a33fe
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.32x32.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.512x512.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.512x512.png
new file mode 100644
index 0000000..89389b4
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.512x512.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.64x64.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.64x64.png
new file mode 100644
index 0000000..84440e9
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.64x64.png differ
diff --git a/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.96x96.png b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.96x96.png
new file mode 100644
index 0000000..0ca63a7
Binary files /dev/null and b/branding/desktop/pixel/mask/alpha/logo.alpha.mask.foreground.96x96.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.1024x1024.png b/branding/desktop/pixel/mask/logo.mask.1024x1024.png
new file mode 100644
index 0000000..e1e01ab
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.1024x1024.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.128x128.png b/branding/desktop/pixel/mask/logo.mask.128x128.png
new file mode 100644
index 0000000..4207f53
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.128x128.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.192x192.png b/branding/desktop/pixel/mask/logo.mask.192x192.png
new file mode 100644
index 0000000..76da48b
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.192x192.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.256x256.png b/branding/desktop/pixel/mask/logo.mask.256x256.png
new file mode 100644
index 0000000..9172fbd
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.256x256.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.32x32.png b/branding/desktop/pixel/mask/logo.mask.32x32.png
new file mode 100644
index 0000000..743a518
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.32x32.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.512x512.png b/branding/desktop/pixel/mask/logo.mask.512x512.png
new file mode 100644
index 0000000..371f72d
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.512x512.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.64x64.png b/branding/desktop/pixel/mask/logo.mask.64x64.png
new file mode 100644
index 0000000..cf2f413
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.64x64.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.96x96.png b/branding/desktop/pixel/mask/logo.mask.96x96.png
new file mode 100644
index 0000000..6d32f4d
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.96x96.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.1024x1024.png b/branding/desktop/pixel/mask/logo.mask.foreground.1024x1024.png
new file mode 100644
index 0000000..d84ba3d
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.1024x1024.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.128x128.png b/branding/desktop/pixel/mask/logo.mask.foreground.128x128.png
new file mode 100644
index 0000000..ea37e0b
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.128x128.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.192x192.png b/branding/desktop/pixel/mask/logo.mask.foreground.192x192.png
new file mode 100644
index 0000000..07c60e4
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.192x192.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.256x256.png b/branding/desktop/pixel/mask/logo.mask.foreground.256x256.png
new file mode 100644
index 0000000..e6dac7d
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.256x256.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.32x32.png b/branding/desktop/pixel/mask/logo.mask.foreground.32x32.png
new file mode 100644
index 0000000..f08ca77
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.32x32.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.512x512.png b/branding/desktop/pixel/mask/logo.mask.foreground.512x512.png
new file mode 100644
index 0000000..dac53af
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.512x512.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.64x64.png b/branding/desktop/pixel/mask/logo.mask.foreground.64x64.png
new file mode 100644
index 0000000..33c790b
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.64x64.png differ
diff --git a/branding/desktop/pixel/mask/logo.mask.foreground.96x96.png b/branding/desktop/pixel/mask/logo.mask.foreground.96x96.png
new file mode 100644
index 0000000..813d347
Binary files /dev/null and b/branding/desktop/pixel/mask/logo.mask.foreground.96x96.png differ
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Icon.png b/src/Client/UniScan.Client.App.Platform.Android/Icon.png
deleted file mode 100755
index 3c39845..0000000
Binary files a/src/Client/UniScan.Client.App.Platform.Android/Icon.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App.Platform.Android/MainActivity.cs b/src/Client/UniScan.Client.App.Platform.Android/MainActivity.cs
index f0d44e3..12aef3d 100755
--- a/src/Client/UniScan.Client.App.Platform.Android/MainActivity.cs
+++ b/src/Client/UniScan.Client.App.Platform.Android/MainActivity.cs
@@ -8,7 +8,7 @@ namespace UniScan.Client.App.Platform.Android;
[Activity(
Label = "UniScan",
Theme = "@style/MyTheme.NoActionBar",
- Icon = "@drawable/icon",
+ Icon = "@mipmap/ic_launcher",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
[IntentFilter(["android.intent.action.MAIN"], Categories = ["android.intent.category.LEANBACK_LAUNCHER"])]
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Properties/AndroidManifest.xml b/src/Client/UniScan.Client.App.Platform.Android/Properties/AndroidManifest.xml
index b9f0c58..77a7ebd 100755
--- a/src/Client/UniScan.Client.App.Platform.Android/Properties/AndroidManifest.xml
+++ b/src/Client/UniScan.Client.App.Platform.Android/Properties/AndroidManifest.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-night-v31/avalonia_anim.xml b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-night-v31/avalonia_anim.xml
deleted file mode 100755
index dde4b5a..0000000
--- a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-night-v31/avalonia_anim.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-v31/avalonia_anim.xml b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-v31/avalonia_anim.xml
deleted file mode 100755
index 94f27d9..0000000
--- a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-v31/avalonia_anim.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-xxxhdpi/ic_desktop.png b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-xxxhdpi/ic_desktop.png
new file mode 100644
index 0000000..7742027
Binary files /dev/null and b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-xxxhdpi/ic_desktop.png differ
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-xxxhdpi/ic_desktop_cutout.png b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-xxxhdpi/ic_desktop_cutout.png
new file mode 100644
index 0000000..18270f3
Binary files /dev/null and b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable-xxxhdpi/ic_desktop_cutout.png differ
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable/splash_screen.xml b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable/splash_screen.xml
index 2e920b4..d48db39 100755
--- a/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable/splash_screen.xml
+++ b/src/Client/UniScan.Client.App.Platform.Android/Resources/drawable/splash_screen.xml
@@ -5,7 +5,7 @@
-
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml b/src/Client/UniScan.Client.App.Platform.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..1256e1c
--- /dev/null
+++ b/src/Client/UniScan.Client.App.Platform.Android/Resources/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/values-v31/styles.xml b/src/Client/UniScan.Client.App.Platform.Android/Resources/values-v31/styles.xml
index c6fd4b5..1dc571f 100755
--- a/src/Client/UniScan.Client.App.Platform.Android/Resources/values-v31/styles.xml
+++ b/src/Client/UniScan.Client.App.Platform.Android/Resources/values-v31/styles.xml
@@ -8,8 +8,8 @@
- false
- @null
- true
-
- - @drawable/avalonia_anim
+ - @color/splash_background
+ - @drawable/ic_desktop
- 1000
- @style/MyTheme.Main
diff --git a/src/Client/UniScan.Client.App.Platform.Android/Resources/values/colors.xml b/src/Client/UniScan.Client.App.Platform.Android/Resources/values/colors.xml
index 59279d5..6539c78 100755
--- a/src/Client/UniScan.Client.App.Platform.Android/Resources/values/colors.xml
+++ b/src/Client/UniScan.Client.App.Platform.Android/Resources/values/colors.xml
@@ -1,4 +1,5 @@
+ #FFFFFF
#FFFFFF
diff --git a/src/Client/UniScan.Client.App.Platform.Android/UniScan.Client.App.Platform.Android.csproj b/src/Client/UniScan.Client.App.Platform.Android/UniScan.Client.App.Platform.Android.csproj
index 54ffcb7..638c231 100755
--- a/src/Client/UniScan.Client.App.Platform.Android/UniScan.Client.App.Platform.Android.csproj
+++ b/src/Client/UniScan.Client.App.Platform.Android/UniScan.Client.App.Platform.Android.csproj
@@ -9,19 +9,13 @@
false
UniScanProject
UniScan Android
- 0.0.5
- 0.0.5
- 1
+ 0.0.6
+ 0.0.6
+ 2
$(AssemblyVersion)
UniScan client for Android
-
-
- Resources\drawable\Icon.png
-
-
-
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/UniScan.Client.App.Platform.Browser.csproj b/src/Client/UniScan.Client.App.Platform.Browser/UniScan.Client.App.Platform.Browser.csproj
index 5878497..8ea7673 100755
--- a/src/Client/UniScan.Client.App.Platform.Browser/UniScan.Client.App.Platform.Browser.csproj
+++ b/src/Client/UniScan.Client.App.Platform.Browser/UniScan.Client.App.Platform.Browser.csproj
@@ -11,7 +11,6 @@
false
false
- 0.0.2
UniScan Web
UniScanProject
UniScan client for web browsers (https://uniscan.dexrn.me)
@@ -20,8 +19,8 @@
https://github.com/UniScanProject/UniScan
UniScanProject
UniScan Web
- 0.1.3
- 0.1.3
+ 0.1.4
+ 0.1.4
@@ -42,4 +41,8 @@
+
+
+
+
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/app.webmanifest b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/app.webmanifest
index 5fdaad6..e7c7d64 100644
--- a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/app.webmanifest
+++ b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/app.webmanifest
@@ -3,17 +3,22 @@
"name": "UniScan Web",
"icons": [
{
- "src": "/assets/logo_128x128.png",
+ "src": "/assets/branding/desktop/pixel/logo.svg",
+ "sizes": "any",
+ "type": "image/svg+xml"
+ },
+ {
+ "src": "/assets/branding/desktop/pixel/logo.128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
- "src": "/assets/logo_512x512.png",
+ "src": "/assets/branding/desktop/pixel/logo.192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
- "src": "/assets/logo_512x512.png",
+ "src": "/assets/branding/desktop/pixel/logo.512x512.png",
"sizes": "512x512",
"type": "image/png"
}
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/README.md b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/README.md
deleted file mode 100644
index 979155e..0000000
--- a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/README.md
+++ /dev/null
@@ -1 +0,0 @@
-AVALONIA LOGOS ARE TEMP UNTIL I CAN EITHER MAKE MY OWN LOGO OR FIND SOMEONE WHO WILL WANT TO MAKE ONE FOR ME
\ No newline at end of file
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/branding b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/branding
new file mode 120000
index 0000000..3d91304
--- /dev/null
+++ b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/branding
@@ -0,0 +1 @@
+../../../../../branding
\ No newline at end of file
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_128x128.png b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_128x128.png
deleted file mode 100644
index b704696..0000000
Binary files a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_128x128.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_192x192.png b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_192x192.png
deleted file mode 100644
index 176aea8..0000000
Binary files a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_192x192.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_400x400.png b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_400x400.png
deleted file mode 100644
index 3c39845..0000000
Binary files a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_400x400.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_512x512.png b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_512x512.png
deleted file mode 100644
index 29b4d8c..0000000
Binary files a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/assets/logo_512x512.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/index.html b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/index.html
index 5217ea7..3f4cfd3 100755
--- a/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/index.html
+++ b/src/Client/UniScan.Client.App.Platform.Browser/wwwroot/index.html
@@ -4,7 +4,15 @@
UniScan Web
-
+
+
+
+
+
+
+
+
+
@@ -34,12 +42,11 @@
-
-
-
-
-
-
+
+
+
+
+
diff --git a/src/Client/UniScan.Client.App/Assets/Branding b/src/Client/UniScan.Client.App/Assets/Branding
new file mode 120000
index 0000000..1c99f10
--- /dev/null
+++ b/src/Client/UniScan.Client.App/Assets/Branding
@@ -0,0 +1 @@
+../../../../branding
\ No newline at end of file
diff --git a/src/Client/UniScan.Client.App/Assets/README.md b/src/Client/UniScan.Client.App/Assets/README.md
deleted file mode 100644
index 979155e..0000000
--- a/src/Client/UniScan.Client.App/Assets/README.md
+++ /dev/null
@@ -1 +0,0 @@
-AVALONIA LOGOS ARE TEMP UNTIL I CAN EITHER MAKE MY OWN LOGO OR FIND SOMEONE WHO WILL WANT TO MAKE ONE FOR ME
\ No newline at end of file
diff --git a/src/Client/UniScan.Client.App/Assets/avalonia-logo.ico b/src/Client/UniScan.Client.App/Assets/avalonia-logo.ico
deleted file mode 100755
index f7da8bb..0000000
Binary files a/src/Client/UniScan.Client.App/Assets/avalonia-logo.ico and /dev/null differ
diff --git a/src/Client/UniScan.Client.App/Assets/logo_128x128.png b/src/Client/UniScan.Client.App/Assets/logo_128x128.png
deleted file mode 100644
index b704696..0000000
Binary files a/src/Client/UniScan.Client.App/Assets/logo_128x128.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App/Assets/logo_192x192.png b/src/Client/UniScan.Client.App/Assets/logo_192x192.png
deleted file mode 100644
index 176aea8..0000000
Binary files a/src/Client/UniScan.Client.App/Assets/logo_192x192.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App/Assets/logo_400x400.png b/src/Client/UniScan.Client.App/Assets/logo_400x400.png
deleted file mode 100644
index 3c39845..0000000
Binary files a/src/Client/UniScan.Client.App/Assets/logo_400x400.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App/Assets/logo_512x512.png b/src/Client/UniScan.Client.App/Assets/logo_512x512.png
deleted file mode 100644
index 29b4d8c..0000000
Binary files a/src/Client/UniScan.Client.App/Assets/logo_512x512.png and /dev/null differ
diff --git a/src/Client/UniScan.Client.App/Core/Module/IUniScanClientAppModule.cs b/src/Client/UniScan.Client.App/Core/Module/IUniScanClientAppModule.cs
index 7c0de1c..6ff5fbf 100755
--- a/src/Client/UniScan.Client.App/Core/Module/IUniScanClientAppModule.cs
+++ b/src/Client/UniScan.Client.App/Core/Module/IUniScanClientAppModule.cs
@@ -2,13 +2,15 @@
using Microsoft.Extensions.DependencyInjection;
using Shiki.ModuleManagement;
using Shiki.ModuleManagement.Module;
+using UniScan.Core.Settings;
using UniScan.Platform;
namespace UniScan.Client.App.Core.Module;
-public class UniScanClientAppModuleInitializationArgs(UniScanApp app) : EventArgs
+public class UniScanClientAppModuleInitializationArgs(UniScanApp app, SettingsManagerBuilder settingsBuilder) : EventArgs
{
public UniScanApp App { get; }
+ public SettingsManagerBuilder SettingsBuilder { get; } = settingsBuilder;
}
public interface IUniScanClientAppModule : IModule
diff --git a/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.Initializers.cs b/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.Initializers.cs
index 55c0373..eb6f7fe 100644
--- a/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.Initializers.cs
+++ b/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.Initializers.cs
@@ -65,8 +65,15 @@ public static async Task InitializeEnvironment(TaskContexts.PreEnvironment ctx,
Log.Debug("Cache path: {Path}", ctx.StandardPaths.CachePath);
#endif
}
+
+ public static void InitializeSettingsBuilder(UniScanAppInitializationPipeline.TaskContexts.PreSettings ctx, ITaskExecutionContext execCtx)
+ {
+ execCtx.Status.Value = "Initializing Settings builder";
+
+ //nothing to do here for now
+ }
- public static void SetupClientMessagePackResolvers(TaskContexts.PreTranslations ctx,
+ public static void SetupClientMessagePackResolvers(TaskContexts.PreSettings ctx,
ITaskExecutionContext execCtx)
{
execCtx.Status.Value = "Initializing client MessagePack resolvers";
@@ -82,7 +89,7 @@ public static void SetupClientMessagePackResolvers(TaskContexts.PreTranslations
MessagePackSerializer.DefaultOptions = MessagePackSerializer.DefaultOptions.WithResolver(resolver);
}
- public static void InitializeSoftwareInfo(UniScanAppInitializationPipeline.TaskContexts.PreTranslations ctx, ITaskExecutionContext execCtx)
+ public static void InitializeSoftwareInfo(UniScanAppInitializationPipeline.TaskContexts.PreSettings ctx, ITaskExecutionContext execCtx)
{
execCtx.Status.Value = "Initializing SoftwareInfo";
@@ -90,7 +97,7 @@ public static void InitializeSoftwareInfo(UniScanAppInitializationPipeline.TaskC
Log.Information("{Info}", UniScanApp.SoftwareInfo);
}
- public static void SetupBindableRegistry(TaskContexts.PreTranslations ctx,
+ public static void SetupBindableRegistry(TaskContexts.PreSettings ctx,
ITaskExecutionContext execCtx)
{
execCtx.Status.Value = "Initializing bindables";
@@ -126,7 +133,7 @@ await mgr.ApplyLanguagesFromSourceAsync(new DirectoryKeyValueLanguageSource(
return new TaskContexts.PreServiceProvider(ctx.UniScanApp, ctx.ServiceCollection, mgr,
ctx.PlatformStandardPaths, ctx.PlatformFileManager,
- ctx.PlatformDirectoryManager);
+ ctx.PlatformDirectoryManager, ctx.SettingsManager);
}
public static void SetupTextComponentResolver(TaskContexts.PreServiceProvider ctx,
@@ -142,12 +149,12 @@ public static void SetupTextComponentResolver(TaskContexts.PreServiceProvider ct
ctx.ServiceCollection.AddSingleton();
}
- public static void SetupSSRSlotRegistry(TaskContexts.PreTranslations ctx, ITaskExecutionContext execCtx)
+ public static void SetupSSRSlotRegistry(TaskContexts.PreSettings ctx, ITaskExecutionContext execCtx)
{
execCtx.Status.Value = "Initializing serverside UI rendering slot registry";
ctx.ServiceCollection.AddSingleton();
}
-
+
public static void SetupSSRUI(TaskContexts.PreServiceProvider ctx, ITaskExecutionContext execCtx)
{
execCtx.Status.Value = "Initializing serverside UI rendering";
@@ -183,7 +190,7 @@ public static TaskContexts.UniScanAppReady InitializeServiceProvider(TaskContext
{
execCtx.Status.Value = "Building ServiceProvider";
- return new TaskContexts.UniScanAppReady(ctx.UniScanApp, ctx.ServiceCollection.BuildServiceProvider());
+ return new TaskContexts.UniScanAppReady(ctx.UniScanApp, ctx.SettingsManager, ctx.ServiceCollection.BuildServiceProvider());
}
public static async Task InitializeRemotes(TaskContexts.UniScanAppReady ctx,
diff --git a/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.TaskContexts.cs b/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.TaskContexts.cs
index 2e5c563..b905ac3 100644
--- a/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.TaskContexts.cs
+++ b/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.TaskContexts.cs
@@ -3,6 +3,7 @@
using Shiki.FileSystem.Abstractions;
using Shiki.Internationalization.Translation;
using Shiki.TaskPipeline.Context;
+using UniScan.Core.Settings;
using UniScan.Platform;
namespace UniScan.Client.App.Core.Pipeline.Initialization;
@@ -20,13 +21,22 @@ public record PreEnvironment(UniScanApp UniScanApp) : ITaskContext
public IPlatformDirectoryManager? DirectoryManager { get; set; }
public IPlatformSerilogInitializer? SerilogInitializer { get; set; }
}
+
+ public record PreSettings(UniScanApp UniScanApp, ServiceCollection ServiceCollection, IPlatformStandardPaths PlatformStandardPaths, IPlatformFileManager PlatformFileManager, IPlatformDirectoryManager PlatformDirectoryManager)
+ : ITransitionableTaskContext
+ {
+ public SettingsManagerBuilder SettingsBuilder { get; } = new SettingsManagerBuilder();
+ public SettingsManager? SettingsManager { get; set; }
+
+ public static PreSettings TransitionFrom(PreEnvironment oldContext) => new(oldContext.UniScanApp, oldContext.ServiceCollection, oldContext.StandardPaths ?? throw new NullReferenceException(), oldContext.FileManager ?? throw new NullReferenceException(), oldContext.DirectoryManager ?? throw new NullReferenceException());
+ }
- public record PreTranslations(UniScanApp UniScanApp, ServiceCollection ServiceCollection, IPlatformStandardPaths PlatformStandardPaths, IPlatformFileManager PlatformFileManager, IPlatformDirectoryManager PlatformDirectoryManager)
- : ITransitionableTaskContext
+ public record PreTranslations(UniScanApp UniScanApp, ServiceCollection ServiceCollection, IPlatformStandardPaths PlatformStandardPaths, IPlatformFileManager PlatformFileManager, IPlatformDirectoryManager PlatformDirectoryManager, SettingsManager SettingsManager)
+ : ITransitionableTaskContext
{
public TranslationManager? TranslationManager { get; set; }
- public static PreTranslations TransitionFrom(PreEnvironment oldContext) => new(oldContext.UniScanApp, oldContext.ServiceCollection, oldContext.StandardPaths ?? throw new NullReferenceException(), oldContext.FileManager ?? throw new NullReferenceException(), oldContext.DirectoryManager ?? throw new NullReferenceException());
+ public static PreTranslations TransitionFrom(PreSettings oldContext) => new(oldContext.UniScanApp, oldContext.ServiceCollection, oldContext.PlatformStandardPaths, oldContext.PlatformFileManager, oldContext.PlatformDirectoryManager, oldContext.SettingsManager ?? throw new NullReferenceException());
}
public record PreServiceProvider(
@@ -35,9 +45,10 @@ public record PreServiceProvider(
TranslationManager TranslationManager,
IPlatformStandardPaths PlatformStandardPaths,
IPlatformFileManager PlatformFileManager,
- IPlatformDirectoryManager PlatformDirectoryManager)
+ IPlatformDirectoryManager PlatformDirectoryManager,
+ SettingsManager SettingsManager)
: ITaskContext;
- public record UniScanAppReady(UniScanApp UniScanApp, IServiceProvider ServiceProvider) : ITaskContext;
+ public record UniScanAppReady(UniScanApp UniScanApp, SettingsManager SettingsManager, IServiceProvider ServiceProvider) : ITaskContext;
}
}
\ No newline at end of file
diff --git a/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.cs b/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.cs
index b09e82f..ab9514d 100644
--- a/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.cs
+++ b/src/Client/UniScan.Client.App/Core/Pipeline/Initialization/UniScanAppInitializationPipeline.cs
@@ -22,12 +22,15 @@ public UniScanAppInitializationPipeline(UniScanApp app)
{
_logger = Log.ForContext();
})
- .ThenTransitionTo()
+ .ThenTransitionTo()//settingsbuilder created in here
+ .ThenRun(Initializers.InitializeSettingsBuilder)
.ThenRun(Initializers.SetupClientMessagePackResolvers)
.ThenRun(Initializers.InitializeSoftwareInfo)
.ThenRun(Initializers.SetupSSRSlotRegistry)
.ThenRunAsync(app.InitializeModules)
.ThenRun(Initializers.SetupBindableRegistry)
+ .ThenRunAsync(app.InitializeSettings)
+ .ThenTransitionTo()
.ThenRunToTransitionToAsync(Initializers.SetupTranslations)
.ThenRun(Initializers.SetupTextComponentResolver)
.ThenRun(Initializers.SetupSSRUI)
diff --git a/src/Client/UniScan.Client.App/UniScan.Client.App.csproj b/src/Client/UniScan.Client.App/UniScan.Client.App.csproj
index 19bfd96..c5e858b 100755
--- a/src/Client/UniScan.Client.App/UniScan.Client.App.csproj
+++ b/src/Client/UniScan.Client.App/UniScan.Client.App.csproj
@@ -196,19 +196,19 @@
-
+
true
PreserveNewest
-
+
true
PreserveNewest
-
+
true
PreserveNewest
-
+
true
PreserveNewest
diff --git a/src/Client/UniScan.Client.App/UniScanApp.Initializers.cs b/src/Client/UniScan.Client.App/UniScanApp.Initializers.cs
index fbd3ea6..f045348 100644
--- a/src/Client/UniScan.Client.App/UniScanApp.Initializers.cs
+++ b/src/Client/UniScan.Client.App/UniScanApp.Initializers.cs
@@ -13,36 +13,45 @@
using UniScan.Client.App.Core.Module.Modules.Internal;
using UniScan.Client.App.Core.Pipeline.Initialization;
using UniScan.Client.Core;
+using UniScan.Core.Settings;
using UniScan.Platform;
namespace UniScan.Client.App;
public partial class UniScanApp
{
- internal async Task InitializeModules(UniScanAppInitializationPipeline.TaskContexts.PreTranslations ctx, ITaskExecutionContext execCtx)
+ internal async Task InitializeSettings(UniScanAppInitializationPipeline.TaskContexts.PreSettings ctx,
+ ITaskExecutionContext execCtx)
+ {
+ execCtx.Status.Value = "Loading settings";
+
+ var res = await ctx.SettingsBuilder.BuildAndLoadAsync();
+
+ ctx.SettingsManager = res.settingsManager;
+ ctx.ServiceCollection.AddSingleton(_ => res.settingsManager);
+ }
+
+
+ internal async Task InitializeModules(UniScanAppInitializationPipeline.TaskContexts.PreSettings ctx, ITaskExecutionContext execCtx)
{
execCtx.Status.Value = "Initializing modules";
var moduleStorageBuilder = new ModuleStorageBuilder()
.WithModuleOfType(null);
-
- await using ServiceProvider serviceProvider = ctx.ServiceCollection.BuildServiceProvider();
- IPlatformStandardPaths standardPaths = serviceProvider.GetRequiredService();
- IPlatformDirectoryManager directoryManager = serviceProvider.GetRequiredService();
- string moduleDir = Path.Combine(standardPaths.DataPath, "modules");
- if (!(await directoryManager.ExistsAsync(moduleDir)))
+ string moduleDir = Path.Combine(ctx.PlatformStandardPaths.DataPath, "modules");
+ if (!(await ctx.PlatformDirectoryManager.ExistsAsync(moduleDir)))
{
Log.Information("Creating new modules folder");
- await directoryManager.CreateDirectoryAsync(moduleDir);
+ await ctx.PlatformDirectoryManager.CreateDirectoryAsync(moduleDir);
}
- moduleStorageBuilder.WithSource(new AssembliesModuleSource(moduleDir), new UniScanClientAppModuleInitializationArgs(this));
+ moduleStorageBuilder.WithSource(new AssembliesModuleSource(moduleDir), new UniScanClientAppModuleInitializationArgs(this, ctx.SettingsBuilder));
string localModules = Path.Combine(Environment.CurrentDirectory, "modules");
- if (await directoryManager.ExistsAsync(localModules))
+ if (await ctx.PlatformDirectoryManager.ExistsAsync(localModules))
{
- moduleStorageBuilder.WithSource(new AssembliesModuleSource(localModules), new UniScanClientAppModuleInitializationArgs(this));
+ moduleStorageBuilder.WithSource(new AssembliesModuleSource(localModules), new UniScanClientAppModuleInitializationArgs(this, ctx.SettingsBuilder));
}
ModuleStorage = await moduleStorageBuilder.BuildAsync();
diff --git a/src/Client/UniScan.Client.App/UniScanApp.axaml.cs b/src/Client/UniScan.Client.App/UniScanApp.axaml.cs
index f06211c..6945043 100755
--- a/src/Client/UniScan.Client.App/UniScanApp.axaml.cs
+++ b/src/Client/UniScan.Client.App/UniScanApp.axaml.cs
@@ -23,6 +23,7 @@
using UniScan.Client.Core;
using UniScan.Client.Core.DI.Factory;
using UniScan.Client.Core.Module.Modules.Internal;
+using UniScan.Core.Settings;
using UniScan.Network.Data.Info.Software;
using UniScan.Platform;
using MainView = UniScan.Client.App.Views.MainView;
@@ -63,6 +64,8 @@ public partial class UniScanApp : Application
public static string VersionString => $"UniScan Client v{SoftwareInfo.AppInfo.Version} ({PlatformAttribute!.Identifier} v{PlatformVersion})";
+ public SettingsManager Manager { get; private set; } = null!;
+
public ModuleStorage? ModuleStorage
{
get;
diff --git a/src/Client/UniScan.Client.App/Views/Global/LoadingView.axaml b/src/Client/UniScan.Client.App/Views/Global/LoadingView.axaml
index 0e0887e..9b1f353 100644
--- a/src/Client/UniScan.Client.App/Views/Global/LoadingView.axaml
+++ b/src/Client/UniScan.Client.App/Views/Global/LoadingView.axaml
@@ -9,7 +9,7 @@
x:DataType="global:LoadingViewModel">
-
+
diff --git a/src/Client/UniScan.Client.App/Views/MainWindow.axaml b/src/Client/UniScan.Client.App/Views/MainWindow.axaml
index 2ff741c..a5a1103 100755
--- a/src/Client/UniScan.Client.App/Views/MainWindow.axaml
+++ b/src/Client/UniScan.Client.App/Views/MainWindow.axaml
@@ -5,7 +5,7 @@
xmlns:views2="clr-namespace:UniScan.Client.App.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="UniScan.Client.App.Views.MainWindow"
- Icon="/Assets/avalonia-logo.ico"
+ Icon="/Assets/Branding/desktop/pixel/logo.ico"
Title="UniScan">
diff --git a/src/Core/UniScan.Core/Bootstrap.cs b/src/Core/UniScan.Core/Bootstrap.cs
index 69dedbc..df7fd13 100644
--- a/src/Core/UniScan.Core/Bootstrap.cs
+++ b/src/Core/UniScan.Core/Bootstrap.cs
@@ -11,7 +11,7 @@
using Shiki.Internationalization;
using Shiki.Internationalization.Component;
using UniScan.Core.State.Node;
-using UniScan.Network.Formatter.Device;
+using UniScan.Core.State.Node.Formatter;
namespace UniScan.Core;
diff --git a/src/Core/UniScan.Core/Settings/IOption.cs b/src/Core/UniScan.Core/Settings/IOption.cs
new file mode 100644
index 0000000..4456504
--- /dev/null
+++ b/src/Core/UniScan.Core/Settings/IOption.cs
@@ -0,0 +1,79 @@
+using ObservableCollections;
+using R3;
+using Shiki.Common.Identity;
+using Shiki.Common.Result;
+using Shiki.Internationalization.Component;
+
+namespace UniScan.Core.Settings;
+
+public interface IReadOnlyOption
+{
+ Identifier Identifier { get; }
+
+ ITextComponent Name { get; }
+ ITextComponent Description { get; }
+
+ Observable ValueChanged { get; }
+
+ Type Type { get; }
+
+ object? GetValue();
+}
+
+public interface IOption : IReadOnlyOption
+{
+ BooleanResult SetValue(object? value);
+}
+
+public interface IReadOnlyOption : IReadOnlyOption
+{
+ new T GetValue();
+}
+
+public interface IOption : IOption, IReadOnlyOption
+{
+ Observable IReadOnlyOption.ValueChanged => Value.AsObservable().Select(_ => Unit.Default).Skip(1);
+
+ IBindableReactiveProperty Value { get; }
+
+ Type IReadOnlyOption.Type => typeof(T);
+
+
+ BooleanResult IOption.SetValue(object? value) => value is T v ? SetValue(v) : new InvalidOperationException("Given value is not of type " + typeof(T));
+ BooleanResult SetValue(T value);
+
+ object? IReadOnlyOption.GetValue() => GetValue();
+ T IReadOnlyOption.GetValue() => Value.Value;
+}
+
+public class SettingOption : IOption
+{
+ public Identifier Identifier { get; }
+ public Identifier CategoryIdentifier { get; }
+
+ public required ITextComponent Name { get; init; }
+ public required ITextComponent Description { get; init; }
+
+ public IBindableReactiveProperty Value { get; }
+
+ public SettingOption(Identifier id, Identifier category, T defaultValue)
+ {
+ Identifier = id;
+ CategoryIdentifier = category;
+ Value = new BindableReactiveProperty(defaultValue);
+ }
+
+ public BooleanResult SetValue(T value)
+ {
+ Value.Value = value;
+ return BooleanResult.Successful;
+ }
+}
+
+public class SettingsCategory(Identifier id, ITextComponent name)
+{
+ public Identifier Id { get; } = id;
+ public ITextComponent Name { get; } = name;
+
+ public Identifier? Parent { get; init; }
+}
\ No newline at end of file
diff --git a/src/Core/UniScan.Core/Settings/SettingsManager.cs b/src/Core/UniScan.Core/Settings/SettingsManager.cs
new file mode 100644
index 0000000..92b2879
--- /dev/null
+++ b/src/Core/UniScan.Core/Settings/SettingsManager.cs
@@ -0,0 +1,178 @@
+using System.Collections.Immutable;
+using ObservableCollections;
+using R3;
+using Serilog;
+using Shiki.Common.Identity;
+using Shiki.Common.Result;
+using Shiki.FileSystem.Storage;
+using UniScan.Core.Settings.Storage;
+
+namespace UniScan.Core.Settings;
+
+public class SettingsManagerBuilder
+{
+ public readonly record struct OptionMetadata(IOption Option, Identifier Storage);
+
+ private readonly Dictionary _options = [];
+ private readonly Dictionary _categories = [];
+ private readonly Dictionary _storages = [];
+
+ public BooleanResult TryAddCategory(SettingsCategory category)
+ {
+ if (!_categories.TryAdd(category.Id, category))
+ return new InvalidOperationException("Category already exists");
+
+ return BooleanResult.Successful;
+ }
+
+ public BooleanResult TryAddOption(IOption option, Identifier storage)
+ {
+ if (!_storages.ContainsKey(storage))
+ {
+ return new KeyNotFoundException("Storage not found");
+ }
+
+ if (!_options.TryAdd(option.Identifier, new OptionMetadata(option, storage)))
+ {
+ return new InvalidOperationException("Option already exists");
+ }
+
+ return BooleanResult.Successful;
+ }
+
+ public BooleanResult TryAddStorage(Identifier id, IOptionStorage storage)
+ {
+ if (!_storages.TryAdd(id, storage))
+ throw new InvalidOperationException("Storage already exists");
+
+ return BooleanResult.Successful;
+ }
+
+ public SettingsManager Build()
+ {
+ //todo
+ return new SettingsManager(_options, _categories, _storages);
+ }
+
+ public async ValueTask<(SettingsManager settingsManager, IReadOnlyCollection> Errors)> BuildAndLoadAsync()//todo we can create another result type later that holds the value with errors
+ {
+ SettingsManager b = Build();
+ var errors = await b.LoadAsync();
+
+ return (b, errors);
+ }
+}
+
+public class SettingsManager : IDisposable
+{
+ private readonly record struct LockableOptionStorageHolder(IOptionStorage OptionStorage, SemaphoreSlim Semaphore);
+
+ private readonly CompositeDisposable _disposables = new CompositeDisposable();
+
+ private readonly Dictionary _options = [];
+ private readonly Dictionary _categories = [];
+ private readonly Dictionary _storages = [];
+
+ private readonly Subject _dirty = new();
+
+ private bool _loadLock = false;
+
+ private ILogger _logger = Log.ForContext();
+
+ internal SettingsManager(Dictionary options, Dictionary categories, Dictionary storages)
+ {
+ _options = options;
+ _categories = categories;
+ _storages = storages.ToDictionary(kvp => kvp.Key, kvp => new LockableOptionStorageHolder(kvp.Value, new SemaphoreSlim(1,1)));
+
+ foreach (SettingsManagerBuilder.OptionMetadata option in _options.Values)
+ {
+ option.Option.ValueChanged.Where(_ => !_loadLock).Subscribe(_ => _dirty.OnNext(option)).AddTo(_disposables);
+ }
+
+ _dirty.Chunk(TimeSpan.FromMilliseconds(500), TimeProvider.System)
+ .Where(c => c.Length > 0)
+ .Subscribe(ids =>
+ {
+ var u = ids.DistinctBy(m => m.Option.Identifier).GroupBy(m => m.Storage).ToImmutableArray();
+
+ foreach (var g in u)
+ {
+ if (_storages.TryGetValue(g.Key, out LockableOptionStorageHolder storage))
+ {
+ //TODO this is probably slow, lets fix it later.
+ var changed = g.Select(m => m.Option).ToImmutableList();
+ var all = _options.Values.Where(m => m.Storage == g.Key)
+ .Select(m => m.Option)
+ .ToImmutableList();
+
+ _ = RunObservedSave(storage, changed, all);
+ }
+ }
+ }).AddTo(_disposables);
+ }
+
+ private async Task RunObservedSave(LockableOptionStorageHolder holder,
+ IReadOnlyCollection changed,
+ IReadOnlyCollection allOptions)
+ {
+ BooleanResult res = await RunSave(holder, changed, allOptions);
+ if (!res.IsSuccessful)
+ {
+ _logger.Error(res.Error, "Observed save failed!");
+ }
+ }
+
+ private async ValueTask> RunSave(LockableOptionStorageHolder holder,
+ IReadOnlyCollection changed,
+ IReadOnlyCollection allOptions)
+ {
+ await holder.Semaphore.WaitAsync();
+
+ var res = await holder.OptionStorage.SaveAsync(changed, allOptions);
+ holder.Semaphore.Release();
+
+ return res;
+ }
+
+ public async ValueTask>> LoadAsync()
+ {
+ _loadLock = true;//maybe should use volatile or some lock but too lazy
+ try
+ {
+ var t = _storages.Select(async kvp =>
+ {
+ LockableOptionStorageHolder holder = kvp.Value;
+
+ var opt = _options.Values.Where(m => m.Storage == kvp.Key).Select(m => m.Option).ToImmutableList();
+
+ await holder.Semaphore.WaitAsync();
+ try
+ {
+ return await holder.OptionStorage.LoadAsync(opt);
+ }
+ finally
+ {
+ holder.Semaphore.Release();
+ }
+ });
+
+ return await Task.WhenAll(t);//maybe should make ResultCollection later
+ }
+ finally
+ {
+ _loadLock = false;
+ }
+ }
+
+ public void Dispose()
+ {
+ _dirty.Dispose();
+ _disposables.Dispose();
+
+ foreach (LockableOptionStorageHolder holder in _storages.Values)
+ {
+ holder.Semaphore.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UniScan.Core/Settings/Storage/IOptionStorage.cs b/src/Core/UniScan.Core/Settings/Storage/IOptionStorage.cs
new file mode 100644
index 0000000..05cd736
--- /dev/null
+++ b/src/Core/UniScan.Core/Settings/Storage/IOptionStorage.cs
@@ -0,0 +1,54 @@
+using Shiki.Common.Result;
+using Shiki.FileSystem.Storage;
+
+namespace UniScan.Core.Settings.Storage;
+
+public interface IOptionStorage
+{
+ ValueTask> LoadAsync(IReadOnlyCollection options);
+ ValueTask> SaveAsync(IReadOnlyCollection changed, IReadOnlyCollection allOptions);
+}
+
+public class SingleOptionStorage(IStorage> storage) : IOptionStorage
+{
+ public async ValueTask> LoadAsync(IReadOnlyCollection options)
+ {
+ if (options.Count == 0)
+ return new ArgumentException("Options is empty", nameof(options));
+
+ if (options.Count > 1)
+ return new ArgumentException("Multiple options provided for single option storage", nameof(options));
+
+ IOption opt = options.First();
+
+ try
+ {
+ T loaded = await storage.LoadAsync();
+ opt.SetValue(loaded);
+ }
+ catch (Exception e)
+ {
+ return e;
+ }
+
+ return BooleanResult.Successful;
+ }
+
+ public async ValueTask> SaveAsync(IReadOnlyCollection changed,
+ IReadOnlyCollection allOptions)
+ {
+ if (changed.Count == 0)
+ return new ArgumentException("Options is empty", nameof(allOptions));
+
+ if (changed.Count > 1)
+ return new ArgumentException("Multiple options provided for single option storage", nameof(allOptions));
+
+ IOption opt = changed.First();
+
+ if (opt.GetValue() is not T d)
+ return new ArgumentException("Changed value is not of correct type for this option storage");
+
+ await storage.SaveAsync(d);
+ return BooleanResult.Successful;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/UniScan.Core/State/Node/Formatter/DeviceNodeFormatter.cs b/src/Core/UniScan.Core/State/Node/Formatter/DeviceNodeFormatter.cs
index 59f5c83..fcb5323 100644
--- a/src/Core/UniScan.Core/State/Node/Formatter/DeviceNodeFormatter.cs
+++ b/src/Core/UniScan.Core/State/Node/Formatter/DeviceNodeFormatter.cs
@@ -2,15 +2,12 @@
using System.Reflection;
using MessagePack;
using MessagePack.Formatters;
-using Serilog;
using Shiki.Common.Identity;
-using Shiki.Common.Serialization.Polymorphism;
using Shiki.Common.Serialization.Registry;
using Shiki.Common.Serialization.Registry.Validators;
-using UniScan.Core.State.Node;
using UniScan.Core.State.Node.Nodes;
-namespace UniScan.Network.Formatter.Device;
+namespace UniScan.Core.State.Node.Formatter;
public abstract class DeviceNodeTypeRegistryValidator : IHasAttributeTypeRegistryValidator
{
diff --git a/src/Server/UniScan.Server.Core/UniScanServer.cs b/src/Server/UniScan.Server.Core/UniScanServer.cs
index c31227f..bdfeead 100755
--- a/src/Server/UniScan.Server.Core/UniScanServer.cs
+++ b/src/Server/UniScan.Server.Core/UniScanServer.cs
@@ -87,7 +87,7 @@ public class UniScanServer
Uri("https://github.com/UniScanProject/UniScan")),
new
RemoteLink(new
- Uri("https://uniscan.dexrn.me/assets/logo_512x512.png"),
+ Uri("https://uniscan.dexrn.me/assets/branding/desktop/pixel/logo.512x512.png"),
"UniScan Web",
new
Uri("https://uniscan.dexrn.me")),
diff --git a/template/README.md.template b/template/README.md.template
index 2520378..36f89e2 100644
--- a/template/README.md.template
+++ b/template/README.md.template
@@ -1,8 +1,10 @@
-# UniScan
+
+
+
UniScan


----
+
Modular scanner/radio client and multi-broadcast server. Plug in a scanner, set it up in the server software, and open
it up to the internet for others to listen to, and control it yourself by logging into an admin user.
@@ -11,4 +13,8 @@ it up to the internet for others to listen to, and control it yourself by loggin
| Name | Version | Description |
|:-----------------------------------------------------------------------------------------------:|:-------:|------------------------------------------------|
-{ProjectRows}
\ No newline at end of file
+{ProjectRows}
+
+## Credits
+(in the future, these will be included in the About page.)
+- [Unobtainable Melon (Unomelon)](https://bsky.app/profile/unomelon.bsky.social) | Creating the base of the logo for me to work off of. (thus helping me learn a little about pixel art in the process)
\ No newline at end of file