Reported via e-mails.
The web-side change that wasn't ported here is
https://github.com/ppy/osu-web/pull/11151. I wanted to port it at the
time but then ran into issues because this logic should *ideally* also
be applied to the beatmap set overlay leaderboards, but those are
hard-glued to `ScoreInfo`, cannot be easily weaned off it to use
`SoloScoreInfo` instead, and I did not want to make `ScoreInfo` even
more of a mess than it already is.
This time I'm just ignoring it and adding a TODO instead because I have
no confidence I will get review eyes on any refactor of the beatmap set
overlay. All I'll say that such refactors would have potentially
beneficial effects on results screens too which also (ab)use
`ScoreInfo`.
Fixes startup sounds from potentially being fetched from the wrong
source if API connection establishment takes longer than the intro
screen takes to load.
Closes https://github.com/ppy/osu/issues/22492.
Resolves one part of
https://github.com/ppy/osu/discussions/32568#discussioncomment-12612928
A few caveats:
- Layout is slightly different than web intentionally. Web does things
that I think will be difficult to reproduce or just plain look bad in
client, such as:
- On web, the metadata info box has 200px min height and 300px max
height. I just hardcoded 300 units.
- On web, user tags and mapper tags are individually scrollable, and
the amount of space taken up by each is calculated in a way that
is - as far as I can tell - indeterminate, and probably influenced
by some flexbox magic. I just made the entire thing scrollable
instead.
- Because song select shares controls with the beatmap set overlay, now
song select says "Mapper Tags" in the header instead of just "Tags"
too. I think this is fine, because people asked for user tags to be
shown in song select too.
- Search query syntax lifted from
https://github.com/ppy/osu-web/pull/12047.
- Using hardcoded English strings for now, will update to the
translations after the next osu-resources localisations update.
Flushes are assumed to have already come from a definitive state change
(read: disconnection). Allowing the exceptions that come from failing
the flushed requests to trigger the `Failing` code paths makes
completely incorrect behaviour possible.
Because it'll fail anyway - there is either no username or no password.
The reason why this is important is that the block was also setting API
state to `Connecting`.
When API is in `RequiresSecondFactorAuth` state, `attemptConnect()` is
called over and over in a loop, with no sleeping, which means that the
scheduler accumulates hundreds of thousands of these delegates. Sure you
could add a sleep in there maybe, but it seems pretty wasteful to have
the `localUser.IsDefault` guard *inside* the schedule anyway, so this is
what I opted for.
It seems that right now these timeouts do not check for actual data
movement, which is to say if a user with a very slow connection is
uploading and it takes more than `Timeout`, their upload will fail.
For now let's set these values high enough that most users will not be
affected.
Currently, there's a period where the API is `Offline` even though it is
about to connect (as soon as the `run` thread starts up).
This can cause any `Queue`d requests to fail if they arrive too early.
To avoid this, let's ensure the `Connecting` state is set as early as
possible.
I noticed in passing that in a very edge case scenario where the API's
`run` thread doesn't run before it is loaded into the game, something
could access it and get a guest `LocalUser` when the local user actually
has a valid login.
Put another way, the `protected HasLogin` could be `true` while
`LocalUser` is `Guest`.
I think we want to avoid this, so I've moved the initial set of the
local user earlier in the initialisation process.
If this is controversial in any way, the PR can be closed and we can
assume no one is ever going to run into this scenario (or that it
doesn't matter enough even if they did).
It proved to be too difficult to deal with the flow that clears user
states on stopping the watching of global presence updates. It's not
helped in the least that friends are updated via the API, so there's a
third flow to consider (and the timings therein - both server-spectator
and friends are updated concurrently).
Simplest is to separate the friends flow, though this does mean some
logic and state duplication.