Closed siepra closed 10 months ago
@Kacper-RF is this something we can work on without @siepra and @vinkabuki ?
Also, we should let users open/paste an invite link and choose a username even if the backend is not running.
"Starting backend" steps can become part of the progress indicator when users are joining a community.
Maybe some quick fix for a better UX would not be to gray out the input but to disable the submit button?
How this task corresponds with https://github.com/TryQuiet/quiet/issues/1657? Should we have a splashscreen? Your last comment here says something about progress indicator but I think we were talking about getting rid of it?
We need designs and very precise description on how starting application should look like on each OS. This is necessary not only for dev team but also for Kinga so she could accept or reject changes.
@holmesworcester could you write your decisions/propositions here?
Okay, so I think the principles are:
here's my ideal picture of how joining goes:
Updated the issue description to reflect these. Follow the issue description!
@EmiM I updated the ticket description. Can you confirm that it is sufficiently clear?
To see the full picture, let's divide our logic holding objects (sagas) into two categories:
While the first ones can be fully operative on their own, the seconds ones requires backend to be up and running. There are two conditions that has to be met in order to be able to interact with backend:
Information about the web socket client connection status can only be reached directly from within mobile
/desktop
package (unless someone knows the way to pass the local selector value up to state-manager
).
Unfortunately, we share the vast majority of the second-type sagas in state-manager
package which means it's hard to suspend its execution until backend becomes operative (for the reason I mentioned above, and also for the fact that changes made to state-manager
affects mobile
and desktop
equally)
So all the possible solutions have their pros and cons:
state-manager
action dispatches through local sagasstate-manager
sagas until backend becomes operativeLet me know what you think about it. Also don't hesitate to share some other ideas
@holmesworcester @vinkabuki @Kacper-RF
Because this issue is focused on the join/create screen, maybe the solution is to show our splash screen until these fields are available, but don't show a place screen when the user is returning to an already joined community.
Does this make sense?
So basically Option 2 above but we only block frontend when a community has not been joined.
I'm also interested in exploring option 3 because that seems required for letting users send messages immediately when the backend is still unavailable, which is desired. But I think we should learn more about iOS and tackle some other stuff before committing to this strategy.
I don't agree because it'll be coming up every time user brings the app back to frontend on iOS. So in fact joining/creating is only a small percentage of cases.
I only marked option number 2 because I wanted to mention all the possibilities, but in fact this is exactly what we've just replaced with blocking inputs (to speed up frontend).
Also I think showing splash screen conditionally in those circumstances will be messy and won't actually improve anything.
Why will showing the splash screen conditionally on join/create screens not improve anything? It seems to be a solution to the problem, i.e. "inactive fields are unexpected and seem broken, so don't show inactive fields".
The way I picture doing it is, add something to the frontend so that instead of showing inactive fields we show something that looks just like our splash screen.
Anyway, a solution to this ticket simply requires not showing grey / inactive fields to the user on the join/create screens without making any other parts of the app worse.
RE: Anyway, a solution to this ticket simply requires not showing grey / inactive fields to the user on the join/create screens without making any other parts of the app worse.
It doesn't really correspond to what you've said earlier:
Right now, if our backend is not yet running, a user cannot start the process of joining or creating a community, because the fields are greyed out [...] Users should be able to start the process of joining or creating a community. We shouldn't do anything that requires the backend until they submit.
Join/create screens visible ASAP
Users should be able to create a community and choose a username instantly with no delays
That's why I claim splash screen won't actually improve anything. It'd only be an alternative way of doing what we already do.
I'm going by the title of the ticket.
The description is a proposed and better solution, which you're saying is hard or messy. If that solution is hard or messy, other solutions are okay too.
It's very unusual for an app to have temporarily inactive fields in the onboarding screens, so users will see brokenness. It's not unusual to have splash screens, so that solves the brokenness, which is the main issue.
Also I don't really get why it's undesirable complexity to hold invite link and username as variables in the frontend and submit them to the backend once it's alive. To me it sounds like something that shouldn't be a hard change, and if it is I'm curious why and if there's something we can do to make changes like this easier. Either solution is good for me.
RE: Also I don't really get why it's undesirable complexity to hold invite link and username as variables in the frontend and submit them to the backend once it's alive
It is not. The challenging part is to distinguish when to submit data to backend
from state-manager
. Once again read carefully what I posted in the comment above or look into the code.
RE: I'm going by the title of the ticket.
Ok, then I'll replace blocking inputs with splash screen. Although I'd change the How it should work: subtitle. Otherwise Kinga will be confused while doing QA session on this task.
Sure, I can change the description.
From your description of the challenge involved in knowing when we can submit to backend, the part that is not clear to me is why the frontend can't retry submission every second until it gets a response, or some other blind strategy that does not require knowing.
Description updated! Looks good? @siepra
RE: why the frontend can't retry submission every second until it gets a response,
That's because it's not frontend (mobile/desktop) but state-manager
that actually talks to the backend.
Here is the sample code of what it should look like to work like you said (and like I would prefer it to work):
// packages/state-manager
export function emitEvent() {
while (true) {
const ready = yield* select(initSelectors.ready) // web socket client is conneted (&other conditions)
if (ready) {
yield* call(socket, socket.emit)
break
}
}
}
The problem is ready
is not reachable within state-manager
.
We would be able to wrap it into yet another frontend saga:
// packages/mobile
import { emitEvent } from '@quiet/state-manager'
while (true) {
const ready = yield* select(initSelectors.ready)
if (ready) {
yield* call(emitEvent)
}
}
Although it means we'd be calling local sagas instead of state-manager directly which would be different from what we do in desktop's containers, and the only responsibility of that sagas would be to suspend event emitting (messy)
I based the view on the following design https://www.figma.com/file/y8h6w8PYR9jyI3zjYHL9Cl/Mobile-%2B-desktop-%2B-prototypes?type=design&node-id=1427-34705&mode=design&t=PSjrUfLPLrGOoVLP-4 Although currently our screens are not 1:1 with Jason's designs (which were made later) so I decided to keep it center-oriented until we catch up with the other components.
https://github.com/TryQuiet/quiet/assets/15381135/bde51631-7185-4bd0-8dd1-d1a6242e2481
Looks great!
It might be worth adding a real splash screen image to replace the 'powered by react native' screen right now, just to make sure the transition between both screens feels nice.
There's a separate issue for it but it might make sense to tackle now.
The problem:
Right now, if our backend is not yet running, a user cannot start the process of joining or creating a community, because the fields are greyed out. This is bad because it interrupts the first time user experience and appears broken: it is very unusual for users to run into inactive fields in an onboarding flow, so users might assume brokenness.
How it should work (ideal solution)
Users should be able to start the process of joining or creating a community. We shouldn't do anything that requires the backend until they submit. Once they submit their community info (community name or invite) and choose their username, they can see a progress indicator. If the backend is not yet running, the progress indicator can say "Starting backend".
How it should work (acceptable solution)
Instead of showing inactive fields on the join/create screens, we can show our splash screen. Ideally it would include an explanatory note in this phase, e.g. "Starting backend".
Note: we should not show a splash screen while the backend is starting when when users are returning to an existing community, because this will make the app much less useful on iOS.
Notes from @siepra:
It also causes greyed-out input on chat screen and context menu dots on channel list screen to "blink" due to short time between restoring the app and initializing backend services.
In
AppDelegate.m
we useapplicationDidEnterBackground
andapplicationWillEnterForeground
lifecycle callbacks to notify react-native about app state changes but unfortunately the UI operations needs react-native context to be active which makes those callbacks not fully effective (changes to UI are being applied only after fully coming back to foreground which makes components "blink"). In fact, we should be usingapplicationWillResignActive
for any UI operations but it turns out it also doesn't reach react-native.There're two sagas responsible for marking UI ready and performing redirections:
onConnectedSaga
andredirectionSaga
but they do well for initial redirections and are not aware of app changing it's state between active and idle