OfficeDev / TeamsFx

Developer tools for building Teams apps
Other
427 stars 164 forks source link

Unable to change body at user level. #7834

Closed AASPLLC closed 1 year ago

AASPLLC commented 1 year ago

Describe the bug "body" is in a _Host.cshtml file cannot have code. This means if you want to add a theme to the body like: "body style="background-color: @somesettingvariable"", you can't. had to use " instead of < & > due to github internal coding.

To Reproduce Try to set a background-color style based on the user logged in for the body in _Host.cshtml. It cannot be static/globally server side.

Expected behavior Need to be able to change body information with c# code while allowing javascript loading.

Additional context I am using the visual studio 2022 built in Teams Toolkit Library version: TeamsFX 1.2.1

ghost commented 1 year ago

Thank you for contacting us! Any issue or feedback from you is quite important to us. We will do our best to fully respond to your issue as soon as possible. Sometimes additional investigations may be needed, we will usually get back to you within 2 days by adding comments to this issue. Please stay tuned.

AASPLLC commented 1 year ago

To add more on why this does not work:

  1. You cannot do an afterrender initialization for the javascript interop because it happens after body:
    <body style="background-color: @jsonSettings.MessagesBackground">
    <component type="typeof(App)" render-mode="ServerPrerendered" /> //<---------------
  2. if you try, you will get an error message saying that the afterrender must be called first in order to get the current user logged in. Just use these in _Host.cshtml if you want to test directly:
    @using Microsoft.TeamsFx
    @using YOURNAMESPACEGOESHERE.Interop.TeamsSDK
    @using Microsoft.AspNetCore.Components
    @inject TeamsFx teamsfx
    @inject TeamsUserCredential teamsUserCredential
    @inject MicrosoftTeams MicrosoftTeams
    @{
    UserInfo teamsUserInfo = await teamsUserCredential.GetUserInfoAsync();
    SomethingCustom jsonSettings= new(teamsUserInfo.OjbectId);
    }

This is pretty much a catch 22 situation.

JerryYangKai commented 1 year ago

Thanks for reporting this issue, I need some time to investigate it and will reply to you if I have update.

JerryYangKai commented 1 year ago

@AASPLLC Hi! From Blazor official doc and samples, the recommendation way is all the Blazor components will under the 'body' tag. So, I am afraid in Blazor framework it needs some workaround to set 'style' for 'body'. We will also continually integrate the latest Blazor into our template.

wrharper-AASP commented 1 year ago

How about a way to do @code{} inside .css files? Would something like that be possible while still keeping it session based (loaded once per user visiting the site)?

JerryYangKai commented 1 year ago

@wrharper-AASP I am not quite an expert of Blazor, I suggest putting this issue here Blazor official repository to ask for help.

wrharper-AASP commented 1 year ago

The issue is because of how TeamsFx is handling the initialization. .css code isn't really a solution to the problem anyway. It is just a workaround even if I managed to get it to work. The main point is that you cannot modify the body ever due to the structure of how TeamsFx is being handled with Blazor.

wrharper-AASP commented 1 year ago

The user needs to be logged into the app "before" the body is loaded or anything else for that matter so people can gather information and setup user specific settings.

JerryYangKai commented 1 year ago

@wrharper-AASP
Thanks for further information, we need more time to investigate it and if have any update I will reply in this thread. I will follow up on this issue.

vnbaaij commented 1 year ago

Hi @AASPLLC @wrharper-AASP,

There are some examples on SO where the body is changed through Javascript. See https://stackoverflow.com/questions/61659727/how-to-change-css-or-class-of-body-element-in-blazor and https://stackoverflow.com/questions/68133016/how-can-i-reach-body-tag-or-another-tag-from-razor-page-in-blazor-webassembly

An easier approach, I think would be to have a sort of container div defined inside the MainLayout.razor (or any other file which is defined as the base layout in the App,razor file). As that container is then a part of the app which is controlled by Blazor, you can do any kind of dynamic style manipulation needed.

TeamsFx is leveraging the Microsoft.Fast.Components.FluentUI library for providing components with a Teams theme. That library also has functionality on board (with the 'FluentDesignSystemProvider' and 'DesignTokens') to change styling. You can take a loot at https://aka.ms/fluentui-blazor to see what is possible (Color and theme selection). Let us know if you need more help with that.

wrharper-AASP commented 1 year ago

None of this will work because you have to find out who is logged in first. You can't find that out until after rendering. The issue here is how the user authentication works with TeamsFx. The theme that is loaded is based on that.

wrharper-AASP commented 1 year ago

To be clear, I don't need help with handling a theme, that's all finished. This is a fundamental flaw with how the authentication/rendering works with TeamsFx.

Since the authentication happens "after" the body is created, you can never have a theme loaded based on the user logged in before it.

tecton commented 1 year ago

Hi @wrharper-AASP @AASPLLC,

Thanks for the advice! TeamsFx SDK is using JS-Interop to call teams-js API like getting user information. As stated in this document:

While an app is prerendering, certain actions, such as calling into JavaScript (JS), aren't possible.

You have to perform this in OnAfterRender{Async} method in order to delay the interop calls.

I think this is a limitation of Blazor render mode instead of a fundamental flaw of TeamsFx. If you want to change the rendered style, you could use StateHasChanged() to rerender the component and change the background color for each user. It could be a style of the component like \<div> in Welcome.razor instead of \<body> element. Does it make sense to you?

wrharper-AASP commented 1 year ago

pieces of the body always show, so the background looks off. I guess I'll have to make a < div> that covers the entire screen to override the problem.

AASPLLC commented 1 year ago

Hmm, no matter what you still have to log in first and wait for that before you can render the loading screen. I can't seem to get the theme to load before seeing a bright white loading screen even if people use a dark theme.

tecton commented 1 year ago

I'm closing this PR, please leave messages or reopen if there's any new questions. Thank you!

pieces of the body always show, so the background looks off. I guess I'll have to make a < div> that covers the entire screen to override the problem.

Yes, I think this could be a workaround to mitigate this problem. You can change the layout of and use a component to cover the screen. Also, disabling the pre-rendering may also be helpful as described in this SO question.

wrharper-AASP commented 1 year ago

<component type="typeof(App)" render-mode="Server" /> <--- no pre-rendering still shows a white screen before anything else even with OnInitialized as suggested.

wrharper-AASP commented 1 year ago

It looks like this will not be possible for my case. There is too many things that need to be loaded to get user data so the screen will be white no matter what theme is setup for users. This can be closed if it was re-opened.