Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Allow for windows to spawn manually #10950

Closed
danielniccoli opened this issue Sep 10, 2024 · 5 comments · Fixed by #11032
Closed

[feat] Allow for windows to spawn manually #10950

danielniccoli opened this issue Sep 10, 2024 · 5 comments · Fixed by #11032

Comments

@danielniccoli
Copy link

danielniccoli commented Sep 10, 2024

Describe the problem

I'm frustrated that windows configured in tauri.conf.json spawn automatically during setup phase. The WindowConfig allows to hide the window by setting visible: false, but that still spawns a hidden window and runs any code that is defined in the page loaded by the webview. In my use-case that is not acceptable, because the main window loads its content from the database and should only run if the database exists and has no pending migrations. Instead, the user should be shown a specific page (e.g., /error) that holds the error message.

This may seemingly be worked around by manually spawning a window during the setup phase, but this requires to pass any of the over 40 WindowConfig properties in rust code which worsens readability in my opinion, instead of keeping them in the configuration.

Describe the solution you'd like

I would like to have a way of manually spawning windows from the WindowConfig. This would also require a new WindowConfig properties to prevent auto-spawning during the setup phase.

Alternatives considered

  • I considered spawning a window using tauri::WebviewWindowBuilder::new(app, "foo", tauri::WebviewUrl::App("/foo".into())).build()?;
    This is not the best workaround as described above.
  • I considered changing the url of the "main" window to the specific error page (e.g., /error), but was advised not to do that because it is possible that Tauri loads / and runs its code, and shows it to the user before I could then navigate to /error in the setup phase.

Additional context

No response

@ConnorKrammer
Copy link

Having recently run into this same problem, there is WindowBuilder.from_config in Tauri v1 and WebviewWindowBuilder.from_config in v2. Unfortunately, I'm not sure what the proper method of creating a WindowConfig from a JSON file is; I could be overlooking it, but I don't think the docs tell you how, and I haven't dug through the Tauri source to see how it's being done for the default Tauri config file. Putting window definitions in the app.windows field in the main Tauri config file obviously isn't an option either, because Tauri will immediately launch every window defined in that field, with no way to delay that process until later.

We can imagine adding a boolean field to the window config definition, like deferCreation, which allows you to define a window without Tauri launching it until asked. This would also let you access the WindowConfig instances Tauri itself generates from the config file and stores in app.config().app.windows. Unfortunately, even if you could do this, the current API for launching a window from Tauri's own config isn't too desirable. From the WebviewWindowBuilder docs example:

let webview_window = tauri::WebviewWindowBuilder::from_config(&app, &app.config().app.windows.get(0).unwrap().clone())
    .unwrap()
    .build()
    .unwrap();

Setting aside the rather noisy call, relative to the simplicity of the task, the crucial part here that defines which window is created is .get(0), which is not very suggestive of which window is being launched, and is fairly fragile in the case that the window array gets reordered in the config file. Additionally, this API doesn't seem to let you define a label for the window, unlike the WebviewWindowBuilder::new() function, which does. I'm therefore uncertain how this interacts with the permission system, which I think is supposed to be defined per-window, according to the window label (though I might be misunderstanding this).

To pursue that point: WindowConfig's docs indicate the presence of a label field, but I've never seen this used in a Tauri config file. The WebviewWindowBuilder::from_config docs state the following:

Initializes a webview window builder from a WindowConfig from tauri.conf.json. Keep in mind that you can’t create 2 windows with the same label so make sure that the initial window was closed or change the label of the new WebviewWindowBuilder.

It's not clear how the "initial window" gets its label—I'm assuming Tauri just sets it to "main" by itself, but I don't know what happens to windows defined in the config beyond the first. Presumably if you tried to create a new window as in the code sample above, it would implicitly receive the label "main", and all the permissions defined for it.

(Is there a reason that the config file defines window definitions in an array, instead of a dict keyed to each window's label? That seems like it would be an improvement in a few regards.)

Overall, there's a bit of a mess in store for anyone who wants to launch the initial window(s) from their own Rust code while still using a JSON file to define the window configuration. I just caved and redefined everything again in code, even though this isn't ideal.

@martpie
Copy link

martpie commented Sep 11, 2024

I think creating a window manually instead of defining it in the conf file. That's how I implemented it for my app.

My windows section in tauri.config.json is empty.

@ConnorKrammer
Copy link

@martpie Yeah, that's the most straightforward alternative, currently. But if we accept that using a config file has readability benefits enough to merit having window definitions in Tauri's config file to start with (I certainly prefer it, for declarative properties), then it would be nice if it worked for all the basic ways in which one might want to create a window, including from code. But you can't actually define a window in Tauri's config unless you want Tauri to create that window immediately, with no way to tell Tauri to not do this that I can see, except to remove the window definition from the config file entirely. But then you lose the benefits of defining a window that way.

@danielniccoli
Copy link
Author

danielniccoli commented Sep 14, 2024

@ConnorKrammer

We can imagine adding a boolean field to the window config definition, like deferCreation, which allows you to define a window without Tauri launching it until asked.

That's exactly what I am suggesting. Although I would not call the property deferCreation because that does not unambiguously express what the property is supposed to do. Defer could still mean that it is spawned automatically at a later point. Something like createAtSetup or autoSpawn would be more expressive.

.get(0), which is not very suggestive of which window is being launched

I agree. Ideally, get() should expect the label to be passed to prevent issues when reordering the configuration e.g., get("main"). But that's not the focus of this feature request and it might warrant opening a separate issue.

It's not clear how the "initial window" gets its label—I'm assuming Tauri just sets it to "main" by itself, but I don't know what happens to windows defined in the config beyond the first.

Yes, the default label is main, as per https://v2.tauri.app/reference/config/#label. Any other window will also get the default label, which will result in an error, because label must be unique.

@martpie

I think creating a window manually instead of defining it in the conf file. That's how I implemented it for my app.

My windows section in tauri.config.json is empty.

I'm not sure why you wrote that. I have already expressed why this approach is not feasible for the use-case.

@amrbashir
Copy link
Member

amrbashir commented Sep 16, 2024

I added create option here #11032

.get(0), which is not very suggestive of which window is being launched

I agree. Ideally, get() should expect the label to be passed to prevent issues when reordering the configuration e.g., get("main"). But that's not the focus of this feature request and it might warrant opening a separate issue.

I don't think we need to add any APIs for this as app.config().app.windows is just a vector and you can just do app.config().app.windows.find(|w| w.label == "main").unwrap()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants