Implement client_status, activities, other docs fixes, organize serializers, Optional<T> overhaul (fix #381)
Created by: uwx
Summary
Closes #381 (closed): Implement missing presence fields.
Details
The following properties were added:
- DiscordPresence.Activities: A list of activities for a member's presence. This is set to a cached empty array of DiscordActivity (or just an empty array on platforms pre-Standard 1.3) so it is never null.
- DiscordPresence.ClientStatus: Platform-dependend statuses for a member's presence. This is an object that has values for Desktop, Mobile and Web statuses.
Following on these, I also made presence-related classes sealed, updated the docs on DiscordPresence properties to reflect more recent terminology (activities instead of statuses), and added a custom serializer for UserStatus (rather than the switch that is used at the moment).
For ClientStatus, I decided to use Optional, during which I encountered a bug/limitation of my old serializer design, and fixing it required a major overhaul to it, so I took the opportunity to make some cleanups:
- I documented all of the public-facing APIs for Optional and extracted the FromValue/FromNoValue methods into a static class so that the type parameters could be inferred by the compiler some of the time.
- This required many automated changes to outside Optional since the signature was changed.
- The JsonConverter and ContractResolver were moved to the Optional class instead of being left in the DiscordJson class. This puts their location in accordance with the other converters elsewhere in the lib.
- Additionally, since the existing converters all use JsonConverterAttribute, I made my converters (including the DiscordUri one) use that attribute as well. This ended up with DiscordJson being cleaned up quite a bit.
For the presence updates, I changed cycles of token -> string -> populate object
to calls to a new method in DiscordJson called PopulateObject which avoids that whole mess. This also clears a "TODO" that was placed by someone probably looking for this solution. I also fixed an oversight that meant that DiscordPresence.Activity
would not have any fields defined the first time a PresenceUpdated event is fired.
Changes proposed
- Add DiscordJson.PopulateObject
- Add DiscordPresence.Activities
- Add DiscordPresence.ClientStatus
- Add (for internal usage) DiscordPresence.InternalActivities, DiscordPresence.RawActivities
- Optional changes:
- Optional converter and contract resolver types made internal
- Use JsonConverterAttribute everywhere
- Document Optional.IfPresent
- Squish (technical term) Optional.Equals
- Squish Optional.Value
- Make Optional._val read-only (it should have been from the start)
- Move Optional.FromValue and FromNoValue to separate static utility classes that use the type parameters in the method signature rather than the class signature, allowing for type inference when the compiler decides it
- This required changes to every class that used it
- Possibly more
Notes
The DiscordPresence type deserves a major overhaul. Unlike some of the other intricate entities in the library, it does not contain a Transport type equivalent, despite it desperately needing one. Without one, a lot of extraneous data is stored in the entity.
I don't know what to do about roles
in Presence Update which is just cryptic to me and flags
in Activity which isn't exposed but I don't know what purpose it serves.
Question: Should for
loops have no braces? What is the convention for D#+?