gui fixes
This commit is contained in:
parent
3bf89fe2fa
commit
b3e87772ec
4 changed files with 81 additions and 338 deletions
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
<!-- Security Headers (Defense in Depth - Backend should also set HTTP headers) -->
|
||||
<!-- Note: connect-src includes localhost:8000 (API), localhost:8334 (MinIO/S3 dev), and production S3 endpoints -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' http://localhost:8000 http://localhost:8334 https://*.digitaloceanspaces.com https://*.amazonaws.com ws://localhost:*; frame-ancestors 'none'; base-uri 'self'; form-action 'self';">
|
||||
<!-- Note: frame-ancestors and X-Frame-Options must be set via HTTP headers, not meta tags -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' http://localhost:8000 http://localhost:8334 https://*.digitaloceanspaces.com https://*.amazonaws.com ws://localhost:*; base-uri 'self'; form-action 'self';">
|
||||
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
||||
<meta http-equiv="X-Frame-Options" content="DENY">
|
||||
<meta name="referrer" content="strict-origin-when-cross-origin">
|
||||
<meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=()">
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// File Path: web/frontend/src/components/Layout/Layout.jsx
|
||||
// Fixed Layout Component - Mobile Menu Now Works Properly
|
||||
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||
import TopNavbar from "./TopNavbar";
|
||||
import Sidebar from "./Sidebar";
|
||||
import { useInactivityTimeout } from "../../hooks/useInactivityTimeout";
|
||||
|
|
@ -292,7 +292,16 @@ function Layout({ children }) {
|
|||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, [isMobile]); // Include isMobile but use functional state updates to avoid loops
|
||||
|
||||
// Track last toggle time to prevent double-clicks
|
||||
const lastToggleRef = useRef(0);
|
||||
|
||||
const handleMenuToggle = useCallback(() => {
|
||||
const now = Date.now();
|
||||
// Prevent double-clicks only (100ms window)
|
||||
if (now - lastToggleRef.current < 100) {
|
||||
return;
|
||||
}
|
||||
lastToggleRef.current = now;
|
||||
setIsSidebarOpen(current => !current);
|
||||
}, []);
|
||||
|
||||
|
|
@ -300,8 +309,17 @@ function Layout({ children }) {
|
|||
setIsSidebarOpen(false);
|
||||
}, []);
|
||||
|
||||
// Track last collapse toggle time to prevent double-clicks
|
||||
const lastCollapseToggleRef = useRef(0);
|
||||
|
||||
// Handle collapse toggle for desktop view
|
||||
const handleCollapseToggle = useCallback(() => {
|
||||
const now = Date.now();
|
||||
// Prevent double-clicks only (100ms window)
|
||||
if (now - lastCollapseToggleRef.current < 100) {
|
||||
return;
|
||||
}
|
||||
lastCollapseToggleRef.current = now;
|
||||
setSidebarCollapsed(current => {
|
||||
const newCollapsedState = !current;
|
||||
localStorage.setItem("sidebarCollapsed", newCollapsedState.toString());
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
UserCircleIcon,
|
||||
ArrowRightOnRectangleIcon,
|
||||
ChevronDownIcon,
|
||||
LockClosedIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import { Modal, Button, useUIXTheme } from "../UIX";
|
||||
|
||||
|
|
@ -248,12 +249,20 @@ function TopNavbar({
|
|||
${isMobile ? "justify-center" : "justify-start ml-4"}
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src="/img/compressed-logo.png"
|
||||
alt="MapleFile Logo"
|
||||
className="h-8 w-auto sm:h-9 md:h-10"
|
||||
draggable="false"
|
||||
/>
|
||||
<Link
|
||||
to="/dashboard"
|
||||
className="flex items-center gap-2 hover:opacity-90 transition-opacity"
|
||||
aria-label="Go to Dashboard"
|
||||
>
|
||||
{/* Lock icon with theme-aware background */}
|
||||
<div className={`${getThemeClasses("bg-gradient-secondary")} p-1.5 sm:p-2 rounded-lg`}>
|
||||
<LockClosedIcon className="h-5 w-5 sm:h-6 sm:w-6 text-white" aria-hidden="true" />
|
||||
</div>
|
||||
{/* MapleFile text - hidden on mobile */}
|
||||
<span className="hidden sm:inline text-white font-semibold text-base md:text-lg tracking-tight">
|
||||
MapleFile
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Spacer for mobile to balance the layout */}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,10 @@ import Layout from "../../../components/Layout/Layout";
|
|||
import { DetailLiteView, Button, useUIXTheme } from "../../../components/UIX";
|
||||
import {
|
||||
ArrowDownTrayIcon,
|
||||
InformationCircleIcon,
|
||||
ComputerDesktopIcon,
|
||||
ShieldCheckIcon,
|
||||
DocumentTextIcon,
|
||||
CodeBracketIcon,
|
||||
HomeIcon,
|
||||
UserIcon,
|
||||
ArrowTopRightOnSquareIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
|
||||
// Constant empty object to prevent re-renders (reused across renders)
|
||||
|
|
@ -21,34 +18,6 @@ const EMPTY_ENTITY_DATA = {};
|
|||
const ExportData = () => {
|
||||
const { getThemeClasses } = useUIXTheme();
|
||||
|
||||
// Theme-aware section styles
|
||||
const sectionStyles = useMemo(() => ({
|
||||
success: {
|
||||
container: getThemeClasses("export-section-success-bg"),
|
||||
border: getThemeClasses("export-section-success-border"),
|
||||
icon: getThemeClasses("export-section-success-icon"),
|
||||
title: getThemeClasses("export-section-success-title"),
|
||||
text: getThemeClasses("export-section-success-text"),
|
||||
muted: getThemeClasses("export-section-success-muted"),
|
||||
},
|
||||
info: {
|
||||
container: getThemeClasses("export-section-info-bg"),
|
||||
border: getThemeClasses("export-section-info-border"),
|
||||
icon: getThemeClasses("export-section-info-icon"),
|
||||
title: getThemeClasses("export-section-info-title"),
|
||||
text: getThemeClasses("export-section-info-text"),
|
||||
},
|
||||
warning: {
|
||||
container: getThemeClasses("export-section-warning-bg"),
|
||||
border: getThemeClasses("export-section-warning-border"),
|
||||
icon: getThemeClasses("export-section-warning-icon"),
|
||||
title: getThemeClasses("export-section-warning-title"),
|
||||
text: getThemeClasses("export-section-warning-text"),
|
||||
muted: getThemeClasses("export-section-warning-muted"),
|
||||
code: getThemeClasses("export-section-warning-code"),
|
||||
},
|
||||
}), [getThemeClasses]);
|
||||
|
||||
// Breadcrumb configuration
|
||||
const breadcrumbItems = useMemo(
|
||||
() => [
|
||||
|
|
@ -74,7 +43,7 @@ const ExportData = () => {
|
|||
const headerConfig = useMemo(
|
||||
() => ({
|
||||
title: "Export Your Data",
|
||||
subtitle: "Download a complete copy of your account data in accordance with GDPR Article 20 (Right to Data Portability)",
|
||||
subtitle: "Download a complete copy of your account data (GDPR Article 20)",
|
||||
icon: ArrowDownTrayIcon,
|
||||
}),
|
||||
[],
|
||||
|
|
@ -83,203 +52,36 @@ const ExportData = () => {
|
|||
// Content sections
|
||||
const contentSections = useMemo(() => {
|
||||
return (
|
||||
<div className="space-y-6" role="main" aria-label="Export data options">
|
||||
{/* Quick Export Option - GDPR Compliance */}
|
||||
<div className="space-y-6" role="main" aria-label="Export data information">
|
||||
{/* Desktop App Required Notice */}
|
||||
<section
|
||||
aria-labelledby="quick-export-heading"
|
||||
className={`${sectionStyles.success.container} border-2 ${sectionStyles.success.border} rounded-xl p-6`}
|
||||
aria-labelledby="desktop-required-heading"
|
||||
className={`${getThemeClasses("bg-accent-light")} border-2 ${getThemeClasses("border-accent")} rounded-xl p-6`}
|
||||
>
|
||||
<div className="flex items-start">
|
||||
<ArrowDownTrayIcon className={`h-6 w-6 ${sectionStyles.success.icon} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||
<ComputerDesktopIcon className={`h-8 w-8 ${getThemeClasses("text-accent")} mr-4 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||
<div className="flex-1">
|
||||
<h3 id="quick-export-heading" className={`text-lg font-semibold ${sectionStyles.success.title} mb-2`}>
|
||||
Quick Export (Web Browser)
|
||||
<h3 id="desktop-required-heading" className={`text-xl font-semibold ${getThemeClasses("text-primary")} mb-3`}>
|
||||
Desktop App Required
|
||||
</h3>
|
||||
<p className={`${sectionStyles.success.text} mb-3`}>
|
||||
In compliance with GDPR Article 20, you can export your data directly from your web browser. This option is suitable for accounts with moderate amounts of data.
|
||||
</p>
|
||||
<p className={`${sectionStyles.success.text} mb-4`}>
|
||||
<strong>What gets exported:</strong> Profile information, collection metadata, and file lists (metadata only - actual file downloads require desktop app due to E2EE).
|
||||
</p>
|
||||
<div className="flex space-x-3">
|
||||
<Button
|
||||
variant="primary"
|
||||
icon={ArrowDownTrayIcon}
|
||||
onClick={() => alert('This feature will be implemented by the backend team. It should generate a JSON export of user profile, collections, and file metadata.')}
|
||||
>
|
||||
Export Metadata (JSON)
|
||||
</Button>
|
||||
</div>
|
||||
<p className={`text-xs ${sectionStyles.success.muted} mt-3`}>
|
||||
<strong>Timeline:</strong> Your export will be available for download within 24 hours. Large exports may take up to 72 hours. You'll receive an email when ready.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Information Notice */}
|
||||
<section
|
||||
aria-labelledby="desktop-info-heading"
|
||||
className={`${sectionStyles.info.container} border-2 ${sectionStyles.info.border} rounded-xl p-6`}
|
||||
>
|
||||
<div className="flex items-start">
|
||||
<InformationCircleIcon className={`h-6 w-6 ${sectionStyles.info.icon} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||
<div className="flex-1">
|
||||
<h3 id="desktop-info-heading" className={`text-lg font-semibold ${sectionStyles.info.title} mb-2`}>
|
||||
Desktop Application for Complete Export
|
||||
</h3>
|
||||
<p className={`${sectionStyles.info.text} mb-3`}>
|
||||
For exporting <strong>complete data including decrypted files</strong>, we recommend using the <strong>MapleFile Desktop Application</strong>. Due to end-to-end encryption, only the desktop app can decrypt and export your actual file contents.
|
||||
</p>
|
||||
<p className={sectionStyles.info.text}>
|
||||
The desktop application efficiently manages the decryption and download of your complete data archive with all files in their original format.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* E2EE Explanation */}
|
||||
<section
|
||||
aria-labelledby="e2ee-heading"
|
||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
||||
>
|
||||
<div className="flex items-start mb-4">
|
||||
<ShieldCheckIcon className={`h-6 w-6 ${getThemeClasses("icon-success")} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||
<div>
|
||||
<h3 id="e2ee-heading" className={`text-lg font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
||||
Why End-to-End Encryption Matters
|
||||
</h3>
|
||||
<p className={`${getThemeClasses("text-secondary")} mb-3`}>
|
||||
Your files are encrypted on your device before they're uploaded to our servers. This means:
|
||||
</p>
|
||||
<ul className={`space-y-2 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Encryption benefits">
|
||||
<li className="flex items-start">
|
||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Only you can decrypt and read your files</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>MapleFile servers cannot access your file contents</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Your privacy is protected even if servers are compromised</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`${getThemeClasses("icon-success")} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Decryption requires your local encryption keys</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Desktop Application Installation */}
|
||||
<section
|
||||
aria-labelledby="install-heading"
|
||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
||||
>
|
||||
<div className="flex items-start mb-4">
|
||||
<ComputerDesktopIcon className={`h-6 w-6 mr-3 flex-shrink-0 mt-0.5 ${getThemeClasses("link-primary")}`} aria-hidden="true" />
|
||||
<div className="flex-1">
|
||||
<h3 id="install-heading" className={`text-lg font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
||||
Install MapleFile Desktop Application
|
||||
</h3>
|
||||
<p className={`${getThemeClasses("text-secondary")} mb-4`}>
|
||||
The MapleFile Desktop Application is a native application that can export your data with full decryption support and an intuitive user interface.
|
||||
</p>
|
||||
|
||||
{/* Repository Link */}
|
||||
<div className={`${getThemeClasses("bg-muted")} border ${getThemeClasses("border-secondary")} rounded-lg p-4 mb-4`}>
|
||||
<div className="flex items-start">
|
||||
<CodeBracketIcon className={`h-5 w-5 ${getThemeClasses("text-muted")} mr-3 mt-0.5`} aria-hidden="true" />
|
||||
<div className="flex-1">
|
||||
<p className={`text-sm font-medium mb-2 ${getThemeClasses("text-primary")}`}>
|
||||
Source Code & Installation Instructions
|
||||
<p className={`${getThemeClasses("text-secondary")} mb-4 text-base`}>
|
||||
Data export is only available through the <strong>MapleFile Desktop Application</strong>. Due to end-to-end encryption, your files can only be decrypted and exported using the native app.
|
||||
</p>
|
||||
<a
|
||||
href="https://codeberg.org/mapleopentech/monorepo/src/branch/main/native/desktop/maplefile"
|
||||
href="https://maplefile.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`${getThemeClasses("link-primary")} hover:underline text-sm font-mono break-all`}
|
||||
aria-label="Download MapleFile Desktop App (opens in new tab)"
|
||||
>
|
||||
https://codeberg.org/mapleopentech/monorepo/src/branch/main/native/desktop/maplefile
|
||||
<Button
|
||||
variant="primary"
|
||||
icon={ArrowTopRightOnSquareIcon}
|
||||
>
|
||||
Download at maplefile.com
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Installation Steps */}
|
||||
<div className="space-y-3">
|
||||
<h4 className={`font-medium ${getThemeClasses("text-primary")}`}>Installation Steps:</h4>
|
||||
<ol className={`space-y-3 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Installation steps">
|
||||
<li className="flex items-start">
|
||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">1.</span>
|
||||
<span>Visit the repository link above</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">2.</span>
|
||||
<span>Follow the installation instructions in the README.md file</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">3.</span>
|
||||
<span>Install the desktop application for your operating system (Windows, macOS, or Linux)</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">4.</span>
|
||||
<span>Log in to your MapleFile account using the desktop application</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`font-semibold mr-3 min-w-[24px] ${getThemeClasses("link-primary")}`} aria-hidden="true">5.</span>
|
||||
<span>Use the export feature to download and decrypt your data</span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* What Gets Exported */}
|
||||
<section
|
||||
aria-labelledby="exported-data-heading"
|
||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
||||
>
|
||||
<div className="flex items-start">
|
||||
<DocumentTextIcon className={`h-6 w-6 ${getThemeClasses("text-muted")} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||
<div className="flex-1">
|
||||
<h3 id="exported-data-heading" className={`text-lg font-semibold mb-3 ${getThemeClasses("text-primary")}`}>
|
||||
What Data Will Be Exported
|
||||
</h3>
|
||||
<p className={`${getThemeClasses("text-secondary")} mb-3`}>
|
||||
The desktop application will export a complete archive of your MapleFile account, including:
|
||||
</p>
|
||||
<ul className={`space-y-2 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Exported data types">
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span><strong>Profile Information:</strong> Your account details, settings, and preferences</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span><strong>Collections (Folders):</strong> All your collection metadata and structure</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span><strong>Files:</strong> All uploaded files, fully decrypted and in their original format</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span><strong>File Metadata:</strong> Creation dates, modification dates, file sizes, and descriptions</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span><strong>Sharing Information:</strong> Details about collections shared with you or by you</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p className={`${getThemeClasses("text-muted")} text-sm mt-4`}>
|
||||
The export will be provided as a ZIP archive with a structured folder hierarchy matching your collections.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GDPR Information */}
|
||||
|
|
@ -290,99 +92,13 @@ const ExportData = () => {
|
|||
<h3 id="gdpr-heading" className={`text-sm font-semibold mb-2 ${getThemeClasses("text-primary")}`}>
|
||||
GDPR Article 20 - Right to Data Portability
|
||||
</h3>
|
||||
<p className={`text-sm ${getThemeClasses("text-secondary")} mb-2`}>
|
||||
You have the right to receive the personal data concerning you, which you have provided to us, in a structured, commonly used and machine-readable format. You also have the right to transmit those data to another controller.
|
||||
</p>
|
||||
<p className={`text-sm ${getThemeClasses("text-muted")}`}>
|
||||
The MapleFile Desktop Application ensures compliance with this right by providing your complete data archive in standard formats (JSON metadata, original file formats).
|
||||
<p className={`text-sm ${getThemeClasses("text-secondary")}`}>
|
||||
You have the right to receive your personal data in a structured, commonly used, and machine-readable format. The MapleFile Desktop Application provides your complete data archive in standard formats.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Security Notice */}
|
||||
<section
|
||||
aria-labelledby="security-heading"
|
||||
className={`${sectionStyles.warning.container} border-2 ${sectionStyles.warning.border} rounded-xl p-6`}
|
||||
>
|
||||
<div className="flex items-start">
|
||||
<ShieldCheckIcon className={`h-6 w-6 ${sectionStyles.warning.icon} mr-3 flex-shrink-0 mt-0.5`} aria-hidden="true" />
|
||||
<div className="flex-1">
|
||||
<h3 id="security-heading" className={`text-lg font-semibold ${sectionStyles.warning.title} mb-2`}>
|
||||
Security: Verify Your Download
|
||||
</h3>
|
||||
<p className={`${sectionStyles.warning.text} mb-3`}>
|
||||
For your security, always verify the authenticity of downloaded software:
|
||||
</p>
|
||||
<ul className={`space-y-2 ${sectionStyles.warning.text}`} role="list" aria-label="Security verification steps">
|
||||
<li className="flex items-start">
|
||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Only download from the official Codeberg repository linked above</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Verify the repository URL matches: <code className={`${sectionStyles.warning.code} px-1 rounded`}>codeberg.org/mapleopentech</code></span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Check that your browser shows a secure HTTPS connection (padlock icon)</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`${sectionStyles.warning.icon} mr-2`} aria-hidden="true">✓</span>
|
||||
<span>Review the release notes and commit history before installation</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p className={`text-sm ${sectionStyles.warning.muted} mt-3`}>
|
||||
<strong>Warning:</strong> Never download MapleFile software from unofficial sources or third-party websites.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Support Section */}
|
||||
<section
|
||||
aria-labelledby="support-heading"
|
||||
className={`${getThemeClasses("bg-card")} rounded-xl shadow-lg border ${getThemeClasses("border-secondary")} p-6`}
|
||||
>
|
||||
<h3 id="support-heading" className={`text-lg font-semibold mb-3 ${getThemeClasses("text-primary")}`}>
|
||||
Need Help?
|
||||
</h3>
|
||||
<p className={`${getThemeClasses("text-secondary")} mb-3`}>
|
||||
If you encounter any issues installing or using the MapleFile Desktop Application, please:
|
||||
</p>
|
||||
<ul className={`space-y-2 ${getThemeClasses("text-secondary")}`} role="list" aria-label="Support options">
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span>Check the README.md file in the repository for detailed documentation</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span>Open an issue on the Codeberg repository for technical support</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className={`mr-2 ${getThemeClasses("link-primary")}`} aria-hidden="true">•</span>
|
||||
<span>Review the application's help documentation and user guide</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{/* Action Button */}
|
||||
<div className="flex justify-center py-6">
|
||||
<a
|
||||
href="https://codeberg.org/mapleopentech/monorepo/src/branch/main/native/desktop/maplefile"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Go to MapleFile Desktop Application Repository (opens in new tab)"
|
||||
>
|
||||
<Button
|
||||
variant="primary"
|
||||
icon={CodeBracketIcon}
|
||||
>
|
||||
Go to MapleFile Desktop Application Repository
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}, [getThemeClasses, sectionStyles]);
|
||||
}, [getThemeClasses]);
|
||||
|
||||
// Field sections for DetailLiteView
|
||||
const fieldSections = useMemo(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue