Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ Open your browser at: **[http://localhost:8080](http://localhost:8080)**

For complete Arch Linux instructions—including future AUR installation placeholders, system dependencies, running with standard virtual environments, and uninstallation—see the [Arch Linux Installation Guide](docs/INSTALL_ARCH.md).

### Windows Standalone Desktop Application

Download `MathWeaveStudio-Beta.exe` from GitHub Releases.
Double-click the executable to launch MathWeave Studio directly in a native desktop window without installing Python or uv.

> **System Prerequisites for Windows Native Mode:**
> MathWeave Studio uses Microsoft Edge WebView2 for its native desktop window. WebView2 is pre-installed on Windows 11 and modern Windows 10 versions. If running on a stripped or offline Windows edition without WebView2, install the official [Microsoft Edge WebView2 Evergreen Runtime](https://go.microsoft.com/fwlink/p/?LinkId=2124703), or launch with `--browser` from the command prompt.

#### Building Standalone EXE on Windows:
```powershell
uv sync --all-groups
uv run pyinstaller mathweave-studio-onefile.spec --clean --noconfirm
```

---

## Documentation
Expand All @@ -103,11 +117,11 @@ For complete Arch Linux instructions—including future AUR installation placeho
MathWeave Studio maintains an automated test suite enforcing Clean Architecture boundary isolation, solver mathematical validity, and UI stability:

```bash
# Run all 206 automated tests
# Run all 229 automated tests
uv run pytest
```

All 206 tests pass with 100% success rate.
All 229 tests pass with 100% success rate.

---

Expand Down
18 changes: 16 additions & 2 deletions README.vi.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ Mở trình duyệt web tại: **[http://localhost:8080](http://localhost:8080)*

Để xem hướng dẫn chi tiết trên Arch Linux—bao gồm trạng thái gói AUR/yay, gói hệ thống, chạy với môi trường ảo tiêu chuẩn và cách gỡ cài đặt sạch sẽ—vui lòng xem [Hướng dẫn cài đặt trên Arch Linux](docs/INSTALL_ARCH.md).

### Ứng dụng Desktop Độc lập trên Windows

Tải tệp `MathWeaveStudio-Beta.exe` từ GitHub Releases.
Nhấp đúp vào tệp EXE để mở MathWeave Studio trực tiếp trong cửa sổ ứng dụng desktop mà không cần cài đặt Python hay uv.

> **Yêu cầu hệ thống cho chế độ Desktop Windows:**
> MathWeave Studio sử dụng Microsoft Edge WebView2 để tạo cửa sổ ứng dụng native. WebView2 đã được tích hợp sẵn trên Windows 11 và các bản cập nhật Windows 10 tiêu chuẩn. Đối với các phiên bản Windows rút gọn hoặc ngoại tuyến chưa có WebView2, vui lòng cài đặt [Microsoft Edge WebView2 Evergreen Runtime](https://go.microsoft.com/fwlink/p/?LinkId=2124703), hoặc chạy ứng dụng từ dòng lệnh với tham số `--browser`.

#### Đóng gói tệp EXE trên Windows:
```powershell
uv sync --all-groups
uv run pyinstaller mathweave-studio-onefile.spec --clean --noconfirm
```

---

## Tài liệu dự án
Expand All @@ -103,11 +117,11 @@ Mở trình duyệt web tại: **[http://localhost:8080](http://localhost:8080)*
MathWeave Studio duy trì bộ kiểm thử tự động toàn diện kiểm soát ranh giới kiến trúc Clean Architecture, tính chính xác của các thuật toán và độ ổn định của giao diện:

```bash
# Chạy toàn bộ 206 bài kiểm thử tự động
# Chạy toàn bộ 229 bài kiểm thử tự động
uv run pytest
```

Toàn bộ 206 bài kiểm thử đều vượt qua với tỷ lệ thành công 100%.
Toàn bộ 229 bài kiểm thử đều vượt qua với tỷ lệ thành công 100%.

---

Expand Down
Binary file added assets/icon.ico
Binary file not shown.
100 changes: 100 additions & 0 deletions mathweave-studio-onefile.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# -*- mode: python ; coding: utf-8 -*-

from PyInstaller.utils.hooks import (
collect_all,
collect_data_files,
collect_dynamic_libs,
collect_submodules,
)

block_cipher = None

datas = []
binaries = []
hiddenimports = []

# Core UI and rendering packages
for pkg in ["nicegui", "plotly", "latex2mathml"]:
datas += collect_data_files(pkg)
hiddenimports += collect_submodules(pkg)

# Application modules and assets
hiddenimports += collect_submodules("math_app")
datas += [("assets", "assets")]

# Pywebview and webview backend
datas += collect_data_files("webview")
binaries += collect_dynamic_libs("webview")
hiddenimports += collect_submodules("webview")

# Windows-specific native dependencies (pythonnet, clr_loader)
for pkg in ["pythonnet", "clr_loader"]:
try:
pkg_datas, pkg_binaries, pkg_hidden = collect_all(pkg)
datas += pkg_datas
binaries += pkg_binaries
hiddenimports += pkg_hidden
except Exception:
pass

hiddenimports += [
# ASGI and WebSocket server
"uvicorn",
"uvicorn.protocols.http.h11_impl",
"uvicorn.protocols.websockets.websockets_impl",
"uvicorn.protocols.websockets.wsproto_impl",
"uvicorn.lifespan.on",
"uvicorn.lifespan.off",
"wsproto",
# Windows pywebview native backend (.NET / WinForms / WebView2)
"clr",
"pythonnet",
"clr_loader",
"clr_loader.ffi",
"webview.platforms.winforms",
"webview.platforms.edgechromium",
"webview.platforms.win32",
# Platform fallback
"qtpy",
]

a = Analysis(
["run.py"],
pathex=["src"],
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=["tkinter", "matplotlib.tests", "scipy", "pytest", "pytest_cov"],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name="MathWeaveStudio-Beta",
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True, # Kept True for beta debugging diagnostics
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon="assets/icon.ico",
)
63 changes: 41 additions & 22 deletions mathweave-studio.spec
Original file line number Diff line number Diff line change
@@ -1,48 +1,67 @@
# -*- mode: python ; coding: utf-8 -*-

from PyInstaller.utils.hooks import collect_data_files, collect_submodules
from PyInstaller.utils.hooks import (
collect_all,
collect_data_files,
collect_dynamic_libs,
collect_submodules,
)
from pathlib import Path

block_cipher = None

datas = []
datas += collect_data_files("nicegui")
datas += collect_data_files("plotly")
datas += collect_data_files("latex2mathml")
datas += [("assets", "assets")]

binaries = []
hiddenimports = []

for pkg in ["nicegui", "plotly", "latex2mathml"]:
datas += collect_data_files(pkg)
hiddenimports += collect_submodules(pkg)

hiddenimports += collect_submodules("math_app")
hiddenimports += collect_submodules("nicegui")
hiddenimports += collect_submodules("plotly")
hiddenimports += collect_submodules("latex2mathml")
datas += [("assets", "assets")]

datas += collect_data_files("webview")
binaries += collect_dynamic_libs("webview")
hiddenimports += collect_submodules("webview")

for pkg in ["pythonnet", "clr_loader"]:
try:
pkg_datas, pkg_binaries, pkg_hidden = collect_all(pkg)
datas += pkg_datas
binaries += pkg_binaries
hiddenimports += pkg_hidden
except Exception:
pass

hiddenimports += [
"qtpy",
"PyQt6",
"PyQt6.QtCore",
"PyQt6.QtGui",
"PyQt6.QtWidgets",
"PyQt6.QtWebEngineWidgets",
"PyQt6.QtWebEngineCore",
"PyQt6.QtWebChannel",
"webview",
"webview.platforms.qt",
"uvicorn",
"uvicorn.protocols.http.h11_impl",
"uvicorn.protocols.websockets.websockets_impl",
"uvicorn.protocols.websockets.wsproto_impl",
"uvicorn.lifespan.on",
"uvicorn.lifespan.off",
"wsproto",
"clr",
"pythonnet",
"clr_loader",
"clr_loader.ffi",
"webview.platforms.winforms",
"webview.platforms.edgechromium",
"webview.platforms.win32",
"qtpy",
]

a = Analysis(
["run.py"],
pathex=["src"],
binaries=[],
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=["tkinter", "matplotlib.tests", "scipy"],
excludes=["tkinter", "matplotlib.tests", "scipy", "pytest", "pytest_cov"],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
Expand All @@ -62,7 +81,7 @@ exe = EXE(
strip=False,
upx=True,
console=False,
icon="assets/icon.png",
icon="assets/icon.ico",
)

coll = COLLECT(
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies = [
"nicegui>=3.18.0",
"numpy>=2.5.4",
"plotly>=7.1.0",
"pythonnet>=3.0.0; sys_platform == 'win32'",
"pywebview>=6.2.1",
"qtpy>=2.4.3",
"sympy>=1.14.0",
Expand Down
4 changes: 3 additions & 1 deletion run.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from __future__ import annotations

import multiprocessing
import sys
from pathlib import Path

Expand All @@ -20,5 +21,6 @@

from math_app.main import main

if __name__ in {"__main__", "__mp_main__"}:
if __name__ == "__main__":
multiprocessing.freeze_support()
main()
Loading
Loading