feat: Implement default welcome page for missing web application
- Added a professional HTML welcome page displayed when no web application is configured. - Enhanced `_load_webapp()` method to support improved path resolution for both development and bundled modes. - Updated error handling to show the welcome page instead of a bare error message when the webapp file is not found. - Modified unit tests to verify the welcome page is displayed in error scenarios. build: Complete Windows and macOS build scripts - Created `build_windows.py` for building Windows executable and optional MSI installer using PyInstaller. - Developed `build_macos.sh` for creating macOS application bundle and DMG image. - Added logging and error handling to build scripts for better user feedback. docs: Add build and icon requirements documentation - Created `PHASE_3_BUILD_SUMMARY.md` detailing the build process, results, and next steps. - Added `resources/icons/README.md` outlining icon requirements and creation guidelines. chore: Sync remotes script for repository maintenance - Introduced `sync_remotes.ps1` PowerShell script to fetch updates from origin and upstream remotes.
This commit is contained in:
parent
90dc09eb4d
commit
f0c96f15b8
10 changed files with 1415 additions and 39 deletions
|
|
@ -11,6 +11,160 @@ from webdrop_bridge.core.drag_interceptor import DragInterceptor
|
|||
from webdrop_bridge.core.validator import PathValidator
|
||||
from webdrop_bridge.ui.restricted_web_view import RestrictedWebEngineView
|
||||
|
||||
# Default welcome page HTML when no webapp is configured
|
||||
DEFAULT_WELCOME_PAGE = """
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WebDrop Bridge</title>
|
||||
<style>
|
||||
* {{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}}
|
||||
|
||||
body {{
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}}
|
||||
|
||||
.container {{
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
padding: 60px 40px;
|
||||
max-width: 600px;
|
||||
text-align: center;
|
||||
}}
|
||||
|
||||
h1 {{
|
||||
color: #667eea;
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 10px;
|
||||
}}
|
||||
|
||||
.version {{
|
||||
color: #999;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 30px;
|
||||
}}
|
||||
|
||||
p {{
|
||||
color: #555;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
}}
|
||||
|
||||
.features {{
|
||||
background: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
padding: 30px;
|
||||
margin: 30px 0;
|
||||
text-align: left;
|
||||
}}
|
||||
|
||||
.features h2 {{
|
||||
color: #333;
|
||||
font-size: 1.2em;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
}}
|
||||
|
||||
.features ul {{
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}}
|
||||
|
||||
.features li {{
|
||||
color: #666;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}}
|
||||
|
||||
.features li:last-child {{
|
||||
border-bottom: none;
|
||||
}}
|
||||
|
||||
.features li:before {{
|
||||
content: "✓ ";
|
||||
color: #667eea;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}}
|
||||
|
||||
.status {{
|
||||
background: #fff3cd;
|
||||
border: 1px solid #ffc107;
|
||||
border-radius: 6px;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
color: #856404;
|
||||
}}
|
||||
|
||||
.status strong {{
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}}
|
||||
|
||||
.footer {{
|
||||
color: #999;
|
||||
font-size: 0.9em;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🌉 WebDrop Bridge</h1>
|
||||
<div class="version">Professional Web-to-File Drag-and-Drop Bridge</div>
|
||||
|
||||
<div class="status">
|
||||
<strong>✓ Application Ready</strong>
|
||||
No web application is currently configured.
|
||||
Configure WEBAPP_URL in your .env file to load your custom application.
|
||||
</div>
|
||||
|
||||
<p>WebDrop Bridge is a professional desktop application that seamlessly converts web-based drag-and-drop interactions into native file operations on Windows and macOS.</p>
|
||||
|
||||
<div class="features">
|
||||
<h2>Key Features</h2>
|
||||
<ul>
|
||||
<li>Drag-and-drop from web interface to desktop</li>
|
||||
<li>Real-time drag state monitoring</li>
|
||||
<li>Path validation and security controls</li>
|
||||
<li>Cross-platform support (Windows & macOS)</li>
|
||||
<li>Professional production-grade architecture</li>
|
||||
<li>Comprehensive logging and monitoring</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p><strong>To configure your web application:</strong></p>
|
||||
<ol style="text-align: left; color: #666; margin-top: 15px;">
|
||||
<li>Create a <code>.env</code> file in your application directory</li>
|
||||
<li>Set <code>WEBAPP_URL</code> to your HTML file path or HTTP URL</li>
|
||||
<li>Example: <code>WEBAPP_URL=file:///./webapp/index.html</code></li>
|
||||
<li>Restart the application</li>
|
||||
</ol>
|
||||
|
||||
<div class="footer">
|
||||
<strong>Version:</strong> {version}<br>
|
||||
<strong>Status:</strong> Ready for configuration
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
"""Main application window for WebDrop Bridge.
|
||||
|
|
@ -77,6 +231,8 @@ class MainWindow(QMainWindow):
|
|||
"""Load the web application.
|
||||
|
||||
Loads HTML from the configured webapp URL or from local file.
|
||||
Supports both bundled apps (PyInstaller) and development mode.
|
||||
Falls back to default welcome page if webapp not found.
|
||||
"""
|
||||
webapp_url = self.config.webapp_url
|
||||
|
||||
|
|
@ -87,12 +243,26 @@ class MainWindow(QMainWindow):
|
|||
# Local file path
|
||||
try:
|
||||
file_path = Path(webapp_url).resolve()
|
||||
|
||||
# If path doesn't exist, try relative to application root
|
||||
# This handles both development and bundled (PyInstaller) modes
|
||||
if not file_path.exists():
|
||||
self.web_view.setHtml(
|
||||
f"<html><body><h1>Error</h1>"
|
||||
f"<p>Web application file not found: {file_path}</p>"
|
||||
f"</body></html>"
|
||||
)
|
||||
# Try relative to application package root
|
||||
app_root = Path(__file__).parent.parent.parent.parent
|
||||
relative_path = app_root / webapp_url.lstrip("file:///").lstrip("./")
|
||||
|
||||
if relative_path.exists():
|
||||
file_path = relative_path
|
||||
else:
|
||||
# Try without leading "./"
|
||||
alt_path = Path(webapp_url.lstrip("file:///").lstrip("./")).resolve()
|
||||
if alt_path.exists():
|
||||
file_path = alt_path
|
||||
|
||||
if not file_path.exists():
|
||||
# Show welcome page with instructions
|
||||
welcome_html = DEFAULT_WELCOME_PAGE.format(version=self.config.app_version)
|
||||
self.web_view.setHtml(welcome_html)
|
||||
return
|
||||
|
||||
# Load local file as file:// URL
|
||||
|
|
@ -100,11 +270,9 @@ class MainWindow(QMainWindow):
|
|||
self.web_view.load(QUrl(file_url))
|
||||
|
||||
except (OSError, ValueError) as e:
|
||||
self.web_view.setHtml(
|
||||
f"<html><body><h1>Error</h1>"
|
||||
f"<p>Failed to load web application: {e}</p>"
|
||||
f"</body></html>"
|
||||
)
|
||||
# Show welcome page on error
|
||||
welcome_html = DEFAULT_WELCOME_PAGE.format(version=self.config.app_version)
|
||||
self.web_view.setHtml(welcome_html)
|
||||
|
||||
def _apply_stylesheet(self) -> None:
|
||||
"""Apply application stylesheet if available."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue