jac-desktop 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jac_desktop-0.2.0/PKG-INFO +85 -0
- jac_desktop-0.2.0/README.md +64 -0
- jac_desktop-0.2.0/_jac_build.py +19 -0
- jac_desktop-0.2.0/jac.toml +46 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-312/config_loader.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-312/native/oauth_broker.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-312/native/webview/webview.na.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-312/plugin.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-312/plugin_config.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-312/targets/native_desktop_target.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-313/config_loader.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-313/native/oauth_broker.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-313/native/webview/webview.na.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-313/plugin.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-313/plugin_config.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-313/targets/native_desktop_target.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-314/config_loader.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-314/native/oauth_broker.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-314/native/webview/webview.na.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-314/plugin.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-314/plugin_config.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/_precompiled/cpython-314/targets/native_desktop_target.jir +0 -0
- jac_desktop-0.2.0/jac_desktop/config_loader.jac +81 -0
- jac_desktop-0.2.0/jac_desktop/impl/config_loader.impl.jac +108 -0
- jac_desktop-0.2.0/jac_desktop/impl/plugin.impl.jac +8 -0
- jac_desktop-0.2.0/jac_desktop/native/oauth_broker.jac +248 -0
- jac_desktop-0.2.0/jac_desktop/native/webview/README.md +46 -0
- jac_desktop-0.2.0/jac_desktop/native/webview/build_libwebview.sh +69 -0
- jac_desktop-0.2.0/jac_desktop/native/webview/install_webkit_deps.sh +62 -0
- jac_desktop-0.2.0/jac_desktop/native/webview/webview.na.jac +139 -0
- jac_desktop-0.2.0/jac_desktop/plugin.jac +12 -0
- jac_desktop-0.2.0/jac_desktop/plugin_config.jac +164 -0
- jac_desktop-0.2.0/jac_desktop/targets/impl/native_desktop_target.impl.jac +258 -0
- jac_desktop-0.2.0/jac_desktop/targets/native_desktop_target.jac +43 -0
- jac_desktop-0.2.0/jac_desktop/tests/test_binding.jac +101 -0
- jac_desktop-0.2.0/jac_desktop/tests/test_native_target.jac +43 -0
- jac_desktop-0.2.0/jac_desktop/tests/test_oauth_broker.jac +187 -0
- jac_desktop-0.2.0/pyproject.toml +24 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jac-desktop
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Jac-native desktop target: one nacompile'd binary + the OS webview.
|
|
5
|
+
Author-email: Jason Mars <jason@mars.ninja>
|
|
6
|
+
Maintainer-email: Jason Mars <jason@mars.ninja>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Keywords: jac,jaclang,jaseci,desktop,webview,native
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Project-URL: Repository, https://github.com/jaseci-labs/jaseci
|
|
11
|
+
Project-URL: Homepage, https://jaseci.org
|
|
12
|
+
Project-URL: Documentation, https://jac-lang.org
|
|
13
|
+
Project-URL: Source, https://github.com/jaseci-labs/jaseci/tree/main/jac-desktop
|
|
14
|
+
Project-URL: Issues, https://github.com/jaseci-labs/jaseci/issues
|
|
15
|
+
Project-URL: Changelog, https://github.com/jaseci-labs/jaseci/blob/main/docs/docs/community/release_notes/jac-desktop.md
|
|
16
|
+
Requires-Dist: jaclang>=0.16.1
|
|
17
|
+
Requires-Dist: jac-client>=0.3.22
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest==8.3.5; extra == "dev"
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# jac-desktop
|
|
23
|
+
|
|
24
|
+
Jac-native desktop target for [Jac](https://jac-lang.org): a desktop app is **one
|
|
25
|
+
`jac nacompile`d binary + the OS's own web engine** - no Rust toolchain, no
|
|
26
|
+
PyInstaller, no separate process.
|
|
27
|
+
|
|
28
|
+
## What you get
|
|
29
|
+
|
|
30
|
+
- A `desktop` build target registered with `jac-client`'s target registry, so
|
|
31
|
+
`jac build --client desktop` and `jac start --client desktop` work once this
|
|
32
|
+
package is installed.
|
|
33
|
+
- The build pipeline:
|
|
34
|
+
1. builds your `cl` codespace with the standard Vite pipeline (via `WebTarget`),
|
|
35
|
+
2. compiles a native host (`na`) that embeds CPython to serve that bundle on a
|
|
36
|
+
loopback port and renders it in the OS-native webview (WebKitGTK on Linux /
|
|
37
|
+
WKWebView on macOS / WebView2 on Windows),
|
|
38
|
+
3. produces a single self-contained binary under `.jac/client/desktop/`.
|
|
39
|
+
|
|
40
|
+
The native webview binding + build tooling live under
|
|
41
|
+
[`jac_desktop/native/webview/`](jac_desktop/native/webview/) (see its README for
|
|
42
|
+
the phase-by-phase design and the dependency-free test suite).
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
pip install jac-client jac-desktop
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Building a desktop app needs the OS web engine + a C toolchain so the native host
|
|
51
|
+
can link `libwebview.so` (built on first use). On Debian/Ubuntu:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
sudo ./jac_desktop/native/webview/install_webkit_deps.sh
|
|
55
|
+
# (build-essential, pkg-config, libgtk-3-dev, libwebkit2gtk-4.1-dev)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Project flow
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
jac create --use fullstack my-app # or any project with a cl codespace
|
|
62
|
+
cd my-app
|
|
63
|
+
jac build --client desktop # -> .jac/client/desktop/<app> (single binary)
|
|
64
|
+
jac start --client desktop # build + launch the native window
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Window geometry + app identity come from `[plugins.desktop]` in `jac.toml`:
|
|
68
|
+
|
|
69
|
+
```toml
|
|
70
|
+
[plugins.desktop]
|
|
71
|
+
name = "my-app"
|
|
72
|
+
|
|
73
|
+
[plugins.desktop.window]
|
|
74
|
+
title = "My App"
|
|
75
|
+
width = 1000
|
|
76
|
+
height = 700
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Status
|
|
80
|
+
|
|
81
|
+
`jac build --client desktop` produces a working, self-contained native desktop
|
|
82
|
+
binary that renders your `cl` UI. The host embeds CPython (it serves the bundle
|
|
83
|
+
and is where `sv` runs in-process). Remaining: wiring the `sv` codespace/walkers
|
|
84
|
+
onto the embedded interpreter, HMR dev mode, and per-OS packaging/signing - see
|
|
85
|
+
[issue #6436](https://github.com/jaseci-labs/jaseci/issues/6436).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# jac-desktop
|
|
2
|
+
|
|
3
|
+
Jac-native desktop target for [Jac](https://jac-lang.org): a desktop app is **one
|
|
4
|
+
`jac nacompile`d binary + the OS's own web engine** - no Rust toolchain, no
|
|
5
|
+
PyInstaller, no separate process.
|
|
6
|
+
|
|
7
|
+
## What you get
|
|
8
|
+
|
|
9
|
+
- A `desktop` build target registered with `jac-client`'s target registry, so
|
|
10
|
+
`jac build --client desktop` and `jac start --client desktop` work once this
|
|
11
|
+
package is installed.
|
|
12
|
+
- The build pipeline:
|
|
13
|
+
1. builds your `cl` codespace with the standard Vite pipeline (via `WebTarget`),
|
|
14
|
+
2. compiles a native host (`na`) that embeds CPython to serve that bundle on a
|
|
15
|
+
loopback port and renders it in the OS-native webview (WebKitGTK on Linux /
|
|
16
|
+
WKWebView on macOS / WebView2 on Windows),
|
|
17
|
+
3. produces a single self-contained binary under `.jac/client/desktop/`.
|
|
18
|
+
|
|
19
|
+
The native webview binding + build tooling live under
|
|
20
|
+
[`jac_desktop/native/webview/`](jac_desktop/native/webview/) (see its README for
|
|
21
|
+
the phase-by-phase design and the dependency-free test suite).
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pip install jac-client jac-desktop
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Building a desktop app needs the OS web engine + a C toolchain so the native host
|
|
30
|
+
can link `libwebview.so` (built on first use). On Debian/Ubuntu:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
sudo ./jac_desktop/native/webview/install_webkit_deps.sh
|
|
34
|
+
# (build-essential, pkg-config, libgtk-3-dev, libwebkit2gtk-4.1-dev)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Project flow
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
jac create --use fullstack my-app # or any project with a cl codespace
|
|
41
|
+
cd my-app
|
|
42
|
+
jac build --client desktop # -> .jac/client/desktop/<app> (single binary)
|
|
43
|
+
jac start --client desktop # build + launch the native window
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Window geometry + app identity come from `[plugins.desktop]` in `jac.toml`:
|
|
47
|
+
|
|
48
|
+
```toml
|
|
49
|
+
[plugins.desktop]
|
|
50
|
+
name = "my-app"
|
|
51
|
+
|
|
52
|
+
[plugins.desktop.window]
|
|
53
|
+
title = "My App"
|
|
54
|
+
width = 1000
|
|
55
|
+
height = 700
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Status
|
|
59
|
+
|
|
60
|
+
`jac build --client desktop` produces a working, self-contained native desktop
|
|
61
|
+
binary that renders your `cl` UI. The host embeds CPython (it serves the bundle
|
|
62
|
+
and is where `sv` runs in-process). Remaining: wiring the `sv` codespace/walkers
|
|
63
|
+
onto the embedded interpreter, HMR dev mode, and per-OS packaging/signing - see
|
|
64
|
+
[issue #6436](https://github.com/jaseci-labs/jaseci/issues/6436).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Bundled PEP 517 build backend — generated by jac bundle, do not edit."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_requires_for_build_wheel(config_settings=None):
|
|
5
|
+
return []
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from jaclang.project.config import get_config
|
|
11
|
+
from jaclang.publish.builder import WheelBuilder
|
|
12
|
+
|
|
13
|
+
proj_root = Path.cwd()
|
|
14
|
+
config = get_config(start_path=proj_root, force_discover=True)
|
|
15
|
+
if config is None:
|
|
16
|
+
raise RuntimeError(f"No jac.toml found in {proj_root}.")
|
|
17
|
+
return WheelBuilder(config=config, project_root=proj_root).build_to(
|
|
18
|
+
Path(wheel_directory)
|
|
19
|
+
).name
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "jac-desktop"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Jac-native desktop target: one nacompile'd binary + the OS webview."
|
|
5
|
+
authors = [{ name = "Jason Mars", email = "jason@mars.ninja" }]
|
|
6
|
+
maintainers = [{ name = "Jason Mars", email = "jason@mars.ninja" }]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
keywords = ["jac", "jaclang", "jaseci", "desktop", "webview", "native"]
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
entry-point = "jac_desktop/plugin.jac"
|
|
12
|
+
|
|
13
|
+
[project.urls]
|
|
14
|
+
repository = "https://github.com/jaseci-labs/jaseci"
|
|
15
|
+
homepage = "https://jaseci.org"
|
|
16
|
+
documentation = "https://jac-lang.org"
|
|
17
|
+
source = "https://github.com/jaseci-labs/jaseci/tree/main/jac-desktop"
|
|
18
|
+
issues = "https://github.com/jaseci-labs/jaseci/issues"
|
|
19
|
+
changelog = "https://github.com/jaseci-labs/jaseci/blob/main/docs/docs/community/release_notes/jac-desktop.md"
|
|
20
|
+
|
|
21
|
+
[project.include]
|
|
22
|
+
packages = ["jac_desktop*"]
|
|
23
|
+
|
|
24
|
+
[project.include.data]
|
|
25
|
+
# Ship the Jac-native webview binding + build tooling so the desktop target can
|
|
26
|
+
# compile a host on the user's machine (libwebview.so is built on first use).
|
|
27
|
+
# Explicit globs so tests/ and build caches don't end up in the wheel.
|
|
28
|
+
jac_desktop = [
|
|
29
|
+
"native/webview/webview.na.jac",
|
|
30
|
+
"native/webview/build_libwebview.sh",
|
|
31
|
+
"native/webview/install_webkit_deps.sh",
|
|
32
|
+
"native/webview/README.md",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[dependencies]
|
|
36
|
+
jaclang = ">=0.16.1"
|
|
37
|
+
jac-client = ">=0.3.22"
|
|
38
|
+
|
|
39
|
+
[optional-dependencies.dev]
|
|
40
|
+
pytest = "==8.3.5"
|
|
41
|
+
|
|
42
|
+
[entrypoints.jac]
|
|
43
|
+
desktop_plugin_config = "jac_desktop.plugin_config:JacDesktopPluginConfig"
|
|
44
|
+
|
|
45
|
+
[entrypoints.jac_client]
|
|
46
|
+
desktop = "jac_desktop.plugin:JacDesktopPlugin"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Configuration loader for jac-desktop.
|
|
2
|
+
|
|
3
|
+
Loads from jac.toml under [plugins.desktop], inheriting PluginConfigBase like
|
|
4
|
+
jac-scale and jac-client. Provides the app identity + window geometry the native
|
|
5
|
+
desktop target bakes into the generated host.
|
|
6
|
+
"""
|
|
7
|
+
import from pathlib { Path }
|
|
8
|
+
import from jaclang.project.plugin_config { PluginConfigBase }
|
|
9
|
+
|
|
10
|
+
"""Desktop app identity (name, identifier, version)."""
|
|
11
|
+
obj DesktopIdentity {
|
|
12
|
+
has name: str,
|
|
13
|
+
identifier: str,
|
|
14
|
+
version: str;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
"""Main window geometry from [plugins.desktop.window]."""
|
|
18
|
+
obj WindowConfig {
|
|
19
|
+
has title: str,
|
|
20
|
+
width: int = 1200,
|
|
21
|
+
height: int = 800,
|
|
22
|
+
min_width: int = 800,
|
|
23
|
+
min_height: int = 600,
|
|
24
|
+
resizable: bool = True;
|
|
25
|
+
|
|
26
|
+
static def from_dict(
|
|
27
|
+
data: dict[str, any], title_fallback: str = ""
|
|
28
|
+
) -> WindowConfig {
|
|
29
|
+
title = str(data.get("title", title_fallback) or title_fallback);
|
|
30
|
+
return WindowConfig(
|
|
31
|
+
title=title,
|
|
32
|
+
width=int(data.get("width", 1200)),
|
|
33
|
+
height=int(data.get("height", 800)),
|
|
34
|
+
min_width=int(data.get("min_width", 800)),
|
|
35
|
+
min_height=int(data.get("min_height", 600)),
|
|
36
|
+
resizable=bool(data.get("resizable", True))
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
"""Default [plugins.desktop] values before merging user jac.toml."""
|
|
42
|
+
obj DesktopDefaultConfig {
|
|
43
|
+
has name: str,
|
|
44
|
+
identifier: str,
|
|
45
|
+
version: str,
|
|
46
|
+
window: WindowConfig;
|
|
47
|
+
|
|
48
|
+
def to_dict -> dict[str, any] {
|
|
49
|
+
return {
|
|
50
|
+
'name': self.name,
|
|
51
|
+
'identifier': self.identifier,
|
|
52
|
+
'version': self.version,
|
|
53
|
+
'window': {
|
|
54
|
+
'title': self.window.title,
|
|
55
|
+
'width': self.window.width,
|
|
56
|
+
'height': self.window.height,
|
|
57
|
+
'min_width': self.window.min_width,
|
|
58
|
+
'min_height': self.window.min_height,
|
|
59
|
+
'resizable': self.window.resizable,
|
|
60
|
+
'fullscreen': False
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
"""Desktop plugin configuration loader."""
|
|
67
|
+
class JacDesktopConfig(PluginConfigBase) {
|
|
68
|
+
override def get_plugin_name(self: JacDesktopConfig) -> str;
|
|
69
|
+
override def get_default_config(self: JacDesktopConfig) -> dict[str, any];
|
|
70
|
+
def get_identity(self: JacDesktopConfig) -> DesktopIdentity;
|
|
71
|
+
def get_window_config(self: JacDesktopConfig) -> WindowConfig;
|
|
72
|
+
def validate(self: JacDesktopConfig) -> None;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
glob _desktop_config_instance: JacDesktopConfig | None = None;
|
|
76
|
+
|
|
77
|
+
"""Get or create the desktop config singleton."""
|
|
78
|
+
def get_desktop_config(project_dir: Path | None = None) -> JacDesktopConfig;
|
|
79
|
+
|
|
80
|
+
"""Reset cached desktop config (for tests)."""
|
|
81
|
+
def reset_desktop_config -> None;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Implementation of jac-desktop configuration loader."""
|
|
2
|
+
import from pathlib { Path }
|
|
3
|
+
import from jaclang.cli.console { console }
|
|
4
|
+
|
|
5
|
+
"""Plugin section name for [plugins.desktop]."""
|
|
6
|
+
impl JacDesktopConfig.get_plugin_name(self: JacDesktopConfig) -> str {
|
|
7
|
+
return "desktop";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
"""Default [plugins.desktop] configuration."""
|
|
11
|
+
impl JacDesktopConfig.get_default_config(self: JacDesktopConfig) -> dict[str, any] {
|
|
12
|
+
project_name = "my-jac-app";
|
|
13
|
+
project_version = "1.0.0";
|
|
14
|
+
try {
|
|
15
|
+
jac_config = self.get_jac_config();
|
|
16
|
+
if jac_config and jac_config.project {
|
|
17
|
+
project_name = jac_config.project.name or project_name;
|
|
18
|
+
project_version = jac_config.project.version or project_version;
|
|
19
|
+
}
|
|
20
|
+
} except Exception {
|
|
21
|
+
console.warning("Failed to load JacConfig, using fallback defaults");
|
|
22
|
+
}
|
|
23
|
+
identifier = _generate_identifier(project_name);
|
|
24
|
+
return DesktopDefaultConfig(
|
|
25
|
+
name=project_name,
|
|
26
|
+
identifier=identifier,
|
|
27
|
+
version=project_version,
|
|
28
|
+
window=WindowConfig(title=project_name)
|
|
29
|
+
).to_dict();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
impl JacDesktopConfig.get_identity(self: JacDesktopConfig) -> DesktopIdentity {
|
|
33
|
+
config = self.load();
|
|
34
|
+
return DesktopIdentity(
|
|
35
|
+
name=str(config.get('name', '')),
|
|
36
|
+
identifier=str(config.get('identifier', '')),
|
|
37
|
+
version=str(config.get('version', '1.0.0'))
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
impl JacDesktopConfig.get_window_config(self: JacDesktopConfig) -> WindowConfig {
|
|
42
|
+
config = self.load();
|
|
43
|
+
identity = self.get_identity();
|
|
44
|
+
window_data: dict[str, any] = {};
|
|
45
|
+
raw_window = config.get('window', {});
|
|
46
|
+
if isinstance(raw_window, dict) {
|
|
47
|
+
window_data = raw_window;
|
|
48
|
+
}
|
|
49
|
+
return WindowConfig.from_dict(window_data, title_fallback=identity.name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
impl JacDesktopConfig.validate(self: JacDesktopConfig) -> None {
|
|
53
|
+
config = self.load();
|
|
54
|
+
name = str(config.get('name', ''));
|
|
55
|
+
if not name {
|
|
56
|
+
raise ValueError(
|
|
57
|
+
"Desktop configuration error: 'name' is required in [plugins.desktop]"
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
window = config.get('window', {});
|
|
61
|
+
width = window.get('width', 1200);
|
|
62
|
+
height = window.get('height', 800);
|
|
63
|
+
min_width = window.get('min_width', 800);
|
|
64
|
+
min_height = window.get('min_height', 600);
|
|
65
|
+
if min_width > width {
|
|
66
|
+
raise ValueError(
|
|
67
|
+
f"Desktop configuration error: window.min_width ({min_width}) "
|
|
68
|
+
f"cannot be greater than window.width ({width})"
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if min_height > height {
|
|
72
|
+
raise ValueError(
|
|
73
|
+
f"Desktop configuration error: window.min_height ({min_height}) "
|
|
74
|
+
f"cannot be greater than window.height ({height})"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
impl get_desktop_config(project_dir: Path | None = None) -> JacDesktopConfig {
|
|
80
|
+
# Module-level singleton mirrors jac-client/jac-scale; not thread-safe.
|
|
81
|
+
global _desktop_config_instance;
|
|
82
|
+
if (
|
|
83
|
+
_desktop_config_instance is not None
|
|
84
|
+
and project_dir != _desktop_config_instance.project_dir
|
|
85
|
+
) {
|
|
86
|
+
_desktop_config_instance = None;
|
|
87
|
+
}
|
|
88
|
+
if _desktop_config_instance is None {
|
|
89
|
+
_desktop_config_instance = JacDesktopConfig(project_dir=project_dir);
|
|
90
|
+
}
|
|
91
|
+
return _desktop_config_instance;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
impl reset_desktop_config -> None {
|
|
95
|
+
global _desktop_config_instance;
|
|
96
|
+
_desktop_config_instance = None;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
def _generate_identifier(name: str) -> str {
|
|
100
|
+
import re;
|
|
101
|
+
cleaned = re.sub(r'[^a-zA-Z0-9.\-]', '', name.lower());
|
|
102
|
+
cleaned = re.sub(r'[.\-]+', '.', cleaned);
|
|
103
|
+
cleaned = cleaned.strip('.');
|
|
104
|
+
if not cleaned or not '.' in cleaned {
|
|
105
|
+
cleaned = f"com.{cleaned}" if cleaned else "com.myapp";
|
|
106
|
+
}
|
|
107
|
+
return cleaned;
|
|
108
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Implementation of jac-desktop runtime plugin hooks."""
|
|
2
|
+
|
|
3
|
+
import from jac_client.plugin.src.targets.registry { ClientTarget }
|
|
4
|
+
import from jac_desktop.targets.native_desktop_target { NativeDesktopTarget }
|
|
5
|
+
|
|
6
|
+
impl JacDesktopPlugin.get_client_targets -> list[ClientTarget] {
|
|
7
|
+
return [NativeDesktopTarget()];
|
|
8
|
+
}
|