Skip to content

feat: cache and use RemoteInfo - #21

Merged
DexrnZacAttack merged 23 commits into
mainfrom
feat/use_server_provided_display_names
Aug 28, 2026
Merged

feat: cache and use RemoteInfo#21
DexrnZacAttack merged 23 commits into
mainfrom
feat/use_server_provided_display_names

Conversation

@DexrnZacAttack

@DexrnZacAttack DexrnZacAttack commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

UniScan.Client.App.Platform.Android

  • Added cache path
  • Added UniScanPlatformAttribute to assembly

UniScan.Client.App.Platform.Browser

  • Added cache path
  • Added UniScanPlatformAttribute to assembly

UniScan.Client.App.Platform.Desktop

  • Added cache path
  • Added UniScanPlatformAttribute to assembly

UniScan.Client.App

  • RemoteInfo is now used

  • Added several remote controls:

    • RemoteInfoControl: Displays the remote logo, title, description, and a set of links
    • RemoteLinkControl: Displays the link's logo, title, and url
  • RemoteInfoView now shows RemoteInfoControl in addition to a bottom area for an optional MOTD that the server may provide.

  • RemoteInfoView is now tabbed, with an Announcements tab for viewing server announcements

  • Improved the look of several views:

    • NotConnectedRemotePageView now shows the remote logo and name, and is now centered
    • DisconnectedRemotePageView now shows the remote logo and name, and is now centered
    • The sidebar in MainView has been expanded to properly show remote logos
    • HomePageView now shows a message when not connected to any remotes
    • HomePageView now shows a logo in each remote expander when available
  • Improved the look of several controls:

    • DeviceListControl now properly fills its available space with devices
    • SidebarRemoteItemControl now displays a logo next to the name if available
  • LoadingViewModel now accepts any TaskPipeline to listen to

  • A loading screen is now shown when connecting to a Remote

  • Added UniScanPlatformAttribute

    • Fixes Android crashing due to GetEntryAssembly() failing due to JNI

Breaking Changes

  • Large restructuring
    • Among the changes, all views and viewmodels were merged into one folder and renamed
  • Moved task context stuff to a new Shiki project

UniScan.Client.Core

  • Added RemoteCacheDto for caching RemoteInfo

  • Added RemoteInfoPacketHandler for handling and setting RemoteInfo

  • Created a new remote connection pipeline (RemoteConnectionPipeline)

  • Added IRemoteServerMutationProxy for mutating RemoteServer without explicitly allowing mutation in the original class definition

  • Added a large storage system (from another project I was working on)

    • Will likely be moved to Shiki in the future along with platform abstractions

Breaking Changes

  • Packet registration and remote loading have been moved out of UniScanClient and into our app initialization pipeline
  • App initialization task contexts no longer store UniScanClient
  • Dissolved most of UniScanClient in favor of a method that adds its services to DI.
    • This means that UniScanClient now doesn't do much; however, it will not be removed incase it needs to store anything that isn't a service.
  • Added UniScanClientDependencyInjection.AddUniScanClient
    • This method performs most of the functions of the old UniScanClient's CreateInstanceAsync, but on an existing DI container.
  • RemoteDto no longer holds a display name
  • Removed RemotesListFile in favor of RemoteStorage which observes a list of Remotes inside IRemoteManager to determine when to save
  • IRemoteFactory now requires a GUID in both Create method definitions
  • RemoteServer constructors now require a GUID and IClientSocketFactory instance

UniScan.Device

Breaking Changes

  • Removed DeviceState.Lock and DeviceState.Attributes
  • Removed IScannerEvents.OnStateUpdated
  • Scanner.State is now a IReadOnlyBindableReactiveProperty

UniScan.Network.Client

  • Added IRemoteConnectionMethod.ToDisplayString()
    • Used primarily to get the display string for a remote that does not have a cached name
  • Added IClientSocketFactory and ClientSocketFactory
    • Used to cut down on constructor parameters by providing a singleton passable object that can create a ClientSocket

UniScan.Network.Server

  • Added ClientsManager
    • Used to hold a global list of currently connected clients and provide a way to broadcast a packet to each one.
  • Added ServerSocket.ClientManager
  • Added SubscribableGroup.Contains(IChannel)

UniScan.Network

  • Added RemoteAnnouncementAuthor
    • This will be replaced by a list of user ids in the future that refer to registered users once an auth and user system is in place

Breaking Changes

  • The protocol version is now 4

  • ISocket.SendRequestAsync now accepts a CancellationToken

  • RemoteAnnouncement now stores a list of authors

  • RemoteLink.Url is now a Uri

  • RemoteInfoPacket is no longer a request packet, and is instead sent by the server whenever desired and consumed by the client

  • Removed GetRemoteInfoPacket

  • SubscribePacket is now a proper MessagePackObject

UniScan.Platform

  • Added IPlatformDirectoryManager.DeleteAsync
  • Added IPlatformDirectoryManager.EnumerateAsync

Breaking Changes

  • Added IPlatformFileSystemManager
    • Used to share method signatures between the file and directory managers
  • Removed IPlatformFileManager.ExistsAsync in favor of IPlatformFileSystemManager.ExistsAsync
  • Removed IPlatformDirectoryManager.ExistsAsync in favor of IPlatformFileSystemManager.ExistsAsync
  • Renamed PlatformDirectoryManager.cs to IPlatformDirectoryManager.cs

UniScan.Platform.Implementations.Native

  • Updated implementations according to UniScan.Platform changes

UniScan.Platform.Implementations.Web

  • Updated implementations according to UniScan.Platform changes

Breaking Changes

  • Moved UniScan.Platform.Implementations.Web.BrowserPaths to UniScan.Client.App.Platform.Browser
  • BrowserFileManager.TransferAsync now creates all subfolders leading up to the destination file

UniScan.Server.Core

  • HostClientsHandler now listens to Scanner.State as an Observable
  • Added some more logging to SubscribePacketHandler
  • Added a temporary static RemoteInfo instance in UniScanServer
  • The server now sends a DisconnectPacket to all clients on shutdown

Breaking Changes

  • ClientSoftwareInfoPacketHandler now sends a RemoteInfoPacket after being accepted
  • Removed GetRemoteInfoPacketHandler
  • SubscribePacketHandler no longer allows subscribing to the same device twice
  • SubscribePacketHandler no longer attempts to send the scanner state when it is null
  • UniScanServer._networkGroupManager now uses MultithreadedGroupManager
    • This is hopefully a fix to some weird bug that macOS users were encountering that would cause UniScan to crash.

UniScan.Server.Host

  • ScannerMeta.SaveAsync now properly disposes of the filestream
  • Now prints when exiting

Fixes #12
Fixes #25

# UniScan.Client.App
- You can no longer add a Display Name from `AddRemoteDialogView`

# UniScan.Client.Core
- `RemoteServer` now uses the Connection Method's display string

## Breaking Changes
- `RemoteDto`, `RemoteServer` no longer accept custom display names
- `IRemoteFactory.Create` no longer accepts a `displayName` parameter

# UniScan.Network.Client
- Added `IRemoteConnectionMethod.ToDisplayString()`
- Implemented `TCPRemoteConnectionMethod.ToDisplayString()`
@github-project-automation github-project-automation Bot moved this to Backlog in UniScan Aug 23, 2026
@DexrnZacAttack DexrnZacAttack moved this from Backlog to Ready in UniScan Aug 23, 2026
@DexrnZacAttack DexrnZacAttack moved this from Ready to In progress in UniScan Aug 23, 2026
…ded_display_names

# Conflicts:
#	Client/UniScan.Client.App/ViewModels/RemoteViewModel.cs
…eline

# UniScan.Client.App
- Created `RemoteConnectionPipeline`, which handles the flow for connecting to a remote, negotiation, and finalization
- `TaskPipeline` now accepts a `CancellationToken` and will handle when an exception is thrown.
- `LoadingViewModel` now accepts loading text

## Breaking Changes
- `ITaskStage` tasks now require a `CancellationToken`

# UniScan.Client.Core
- Connecting is no longer done through `RemoteServer`
  - Instead, it has been transformed into a `TaskPipeline` in `UniScan.Client.App`
    - I intend on bringing `TaskPipeline` into either `Shiki.Common` or `UniScan.Client.Core` in the future, and moving the pipeline creation back into RemoteServer

## Breaking Changes
- Removed `RemoteServer.RunConnectionAsync`

# UniScan.Network
- `ISocket.SendRequestAsync` now accepts a `CancellationToken`

# UniScan.Network.Client
- `TCPRemoteConnectionMethod.ConnectAsync` now awaits `bootstrap.ConnectAsync()`
- `ClientSocket.StartAsync` now stops the socket on exception
- `ClientSocket.SendRequestAsync` now accepts a `CancellationToken`

# UniScan.Server.Core
- Now has extra logging on exit
# UniScan.Client.App
- Now sets `ServerAttribute` on the `RemoteServer` after connecting
- `RemoteControlView` and `MainPageView` now bind to `Remote.DisplayName.Value`

# UniScan.Client.Core
- Added `RemoteServer.RemoteInfo`, `RemoteServer._remoteInfo`, and `IRemoteServerMutationProxy.SetRemoteInfo(RemoteInfo)`
- Made logger in `DisconnectPacketHandler` use the correct context
- Created `RemoteInfoPacketHandler` which handles and calls `IRemoteServerMutationProxy.SetRemoteInfo(RemoteInfo)` on `RemoteServer`
  - Later I will make this be cached too.

- Added `Microsoft.Extensions.Logging.Abstractions` and `Serilog.Extensions.Logging`

## Breaking Changes
- `RemoteServer.DisplayName` is now an IReadOnlyBindableReactiveProperty<string> and will automatically use `RemoteServer.RemoteInfo.DisplayName` if available

# UniScan.Network

## Breaking Changes
- The protocol version is now `2`
- `RemoteInfo` is no longer a `readonly record struct`
- `RemoteInfoPacket` is no longer a response packet
- Removed `GetRemoteInfoPacket`

# UniScan.Server.Core
- Now sends `RemoteInfoPacket` after receiving `ClientSoftwareInfoPacket`
- Removed `GetRemoteInfoPacketHandler`
- Created a temporary test `RemoteInfo` instance at `UniScanServer.RemoteInfo`
# UniScan.Client.Core
- Added an overload for `IRemoteFactory.Create` which accepts a `RemoteDto`
- `RemotesListFile.LoadAsync` now calls the new `IRemoteFactory.Create` overload
- Added a constructor overload for `RemoteServer` which accepts a nullable `RemoteInfo` instance
- `UniScanClient` now tracks remotes

## Breaking Changes
- `RemoteDto` now requires an instance of `RemoteCacheDto`
…n separate folder, etc

note: Storage stuff is brought from diff project I was working on
also note: taskpipeline moved to Shiki
…anager.EnumerateAsync`, also implement for web.
# UniScan.Client.App
- Subscribing to a device now functions like it should, sending the packet correctly.
- Added `RemoteInfoView`
   - Displays the remote info like the title, logo, description, and links.
- Added `RemoteLinkView`
   - Displays the link's logo, title, and clicking will open its URL in your browser
- `RemoteViewModel` now stores a `RemoteInfoViewModel` which is passed to other viewmodels that may need it
- `RemoteControlView` now shows the logo provided by the server, if available.
- `MainPageView`'s remote cards now show the logo provided by the server, if available.
- `MainRemotePageView` now displays the `RemoteInfoView`, and an extra bottom toolbar containing the server's MOTD, if available.
- `MainView`'s DrawerPage sidebar has been widened while compact.
- `MainWindow` now uses the correct window title.

## Breaking Changes
- Packet registration and remote loading have been moved out of `UniScanClient` and into our app initialization pipeline
- App initialization task contexts no longer store `UniScanClient`
- Updated `MainViewModel` according to  the changes in `UniScanClient`

# UniScan.Client.Core

## Breaking Changes
- Dissolved most of `UniScanClient` in favor of a method that adds its services to DI.
  - This means that `UniScanClient` now doesn't do much; however, it will not be removed incase it needs to store anything that isn't a service.
- Added `UniScanClientDependencyInjection.AddUniScanClient`
  - This method performs most of the functions of the old `UniScanClient`'s `CreateInstanceAsync`, but on an existing DI container.

# UniScan.Device

## Breaking Changes
- `Scanner.State` is now `IReadOnlyBindableReactiveProperty<DeviceState?>`
- Removed `IScannerEvents.OnStateUpdated`

# UniScan.Network
- Properly set up `SubscribePacket` as a MessagePack object

## Breaking Changes
- The protocol version is now `3`
- `RemoteLink.Url` is now a `Uri`
- Removed `ScannerRegistrationPacket`

# UniScan.Network.Client
- Created `IClientSocketFactory` and `ClientSocketFactory`
  - Intended to be passed wherever a socket may be needed, instead of having to pass all of `ClientSocket`'s ctor's param types.

# UniScan.Network.Server
- Created `ClientsManager`
  - Used to keep track of all connected clients, and allows for broadcasting a single packet across all connected clients.
- Added `ServerSocket.ClientManager`

# UniScan.Server.Core
- `HostClientsHandler` now subscribes to `Scanner.State` instead of subscribing to the old `IScannerEvents.OnStateUpdated`
- Added more info to the temporary `UniScanServer.RemoteInfo`
- `UniScanServer.ExitAsync()` now sends a `DisconnectPacket` to all clients.

## Breaking Changes
- `SubscribePacketHandler` no longer responds with a `ScannerRegistrationPacket`, as that has been removed.
# UniScan.Client.App
- `NotConnectedRemotePageViewModel` now handles disconnects better
- `MainRemotePageVIew` is now tabbed, with an added Announcements page.

# UniScan.Network
- Added `RemoteAnnouncementAuthor`
  - I am almost certain that this will be replaced once we have a proper user system in place.

## Breaking Changes
- The protocol version is now `4`
- `RemoteAnnouncement` now stores a list of `RemoteAnnouncementAuthors`

# UniScan.Network.Server
- Added `SubscribableGroup.Contains(IChannel)`

# UniScan.Server.Core
- Added `HostClientsHandler.Contains(IChannel)`
- Clients are now sent a falsy acknowledgement when they attempt to subscribe to the same scanner more than once
- `UniScanServer._networkGroupManager` now temporarily uses `MultithreadedGroupManager` until settings and a provider is made.
- Fixed opening and never closing the file handle in `ScannerMeta.SaveAsync`
@DexrnZacAttack DexrnZacAttack moved this from In progress to In review in UniScan Aug 27, 2026
@DexrnZacAttack
DexrnZacAttack marked this pull request as ready for review August 27, 2026 10:54
@DexrnZacAttack DexrnZacAttack self-assigned this Aug 27, 2026
@DexrnZacAttack
DexrnZacAttack marked this pull request as draft August 27, 2026 10:55
@DexrnZacAttack DexrnZacAttack changed the title feat: remove display name from RemoteServer feat: cache and use RemoteInfo Aug 28, 2026
@DexrnZacAttack
DexrnZacAttack marked this pull request as ready for review August 28, 2026 04:35
@DexrnZacAttack
DexrnZacAttack merged commit 791a302 into main Aug 28, 2026
56 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in UniScan Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

UniScan on Android crashes due to usage of GetEntryAssembly() Drop display name from remotes on client side

1 participant