@@ -3,74 +3,26 @@ import './aboutModal.css';
33import { createPortal } from 'react-dom' ;
44import logo from '../assets/128x128@2x.png' ;
55import { useLanguage } from '../i18n/LanguageContext' ;
6- import LicenseManager from '../premium/LicenseManager' ;
76
87import { getRunningVersion , getAvailableVersion , compareVersions } from '../utils/version' ;
98
109interface AboutModalProps {
1110 open : boolean ;
1211 onClose : ( ) => void ;
13- showToast ?: ( message : string , type : 'success' | 'error' | 'info' | 'warning' ) => void ;
1412}
1513
16- export function AboutModal ( { open, onClose, showToast } : AboutModalProps ) {
14+ export function AboutModal ( { open, onClose } : AboutModalProps ) {
1715 const { t } = useLanguage ( ) ;
1816
19- const [ lastUpdated , setLastUpdated ] = React . useState < string > ( 'Sun Dec 7 2025' ) ;
2017 const [ version , setVersion ] = React . useState < string > ( '' ) ;
2118 const [ availableVersion , setAvailableVersion ] = React . useState < string > ( '' ) ;
22- const [ name , setName ] = React . useState ( '' ) ;
23- const [ email , setEmail ] = React . useState ( '' ) ;
24- const [ licenseKey , setLicenseKey ] = React . useState ( '' ) ;
25- const [ type , setType ] = React . useState ( '' ) ;
26- const [ isLicenseValid , setIsLicenseValid ] = React . useState ( false ) ;
27-
28- React . useEffect ( ( ) => {
29- const storedEmail = LicenseManager . getStoredEmail ( ) ;
30- if ( storedEmail ) setEmail ( storedEmail ) ;
31- const storedLicenseKey = LicenseManager . getStoredLicenseKey ( ) ;
32- if ( storedLicenseKey ) setLicenseKey ( storedLicenseKey ) ;
33- const storedType = LicenseManager . getStoredType ( ) ;
34- if ( storedType ) setType ( storedType ) ;
35- const storedName = localStorage . getItem ( 'easyeditor-user-name' ) ;
36- if ( storedName ) setName ( storedName ) ;
37-
38- // Check initial license state
39- if ( LicenseManager . hasActiveLicense ( ) ) {
40- setIsLicenseValid ( true ) ;
41- }
42-
43- // Subscribe to license changes to update type
44- const unsubscribe = LicenseManager . subscribe ( ( ) => {
45- setIsLicenseValid ( LicenseManager . hasActiveLicense ( ) ) ;
46- const updatedType = LicenseManager . getType ( ) ;
47- setType ( updatedType ) ;
48- } ) ;
49-
50- return ( ) => unsubscribe ( ) ;
51- } , [ ] ) ;
52-
53- const handleSaveLicense = async ( ) => {
54- localStorage . setItem ( 'easyeditor-user-name' , name ) ;
55- await LicenseManager . setLicenseData ( email , licenseKey ) ;
56- const valid = LicenseManager . hasActiveLicense ( ) ;
57- setIsLicenseValid ( valid ) ;
58- setType ( LicenseManager . getType ( ) ) ;
59- if ( ! valid && showToast ) {
60- showToast ( t ( 'about.invalid_license' ) || 'Invalid license or email' , 'error' ) ;
61- }
62- } ;
63-
6419 React . useEffect ( ( ) => {
6520 ( async ( ) => {
6621 const v = await getRunningVersion ( ) ;
6722 setVersion ( v ) ;
6823
6924 const avInfo = await getAvailableVersion ( ) ;
7025 setAvailableVersion ( avInfo . version ) ;
71- if ( avInfo . date ) {
72- setLastUpdated ( avInfo . date ) ;
73- }
7426 } ) ( ) ;
7527 } , [ ] ) ;
7628 if ( ! open ) return null ;
@@ -102,128 +54,75 @@ export function AboutModal({ open, onClose, showToast }: AboutModalProps) {
10254 </ div >
10355 </ div >
10456 < div className = "about-grid" >
105- < div className = "about-card" >
106- < h3 > { t ( 'about.what_it_is' ) } </ h3 >
107- < p >
108- { t ( 'about.what_it_is_desc' ) }
109- </ p >
110- </ div >
111- < div className = "about-card" >
112- < h3 > { t ( 'about.what_it_does' ) } </ h3 >
113- < ul >
114- < li > { t ( 'about.what_it_does_li1' ) } </ li >
115- < li > { t ( 'about.what_it_does_li3' ) } </ li >
116- </ ul >
117- </ div >
118- < div className = "about-card" >
119- < h3 > { t ( 'about.custom_themes' ) } </ h3 >
120- < p >
121- { t ( 'about.custom_themes_desc1' ) }
122- </ p >
123- </ div >
124- < div className = "about-card" >
125- < h3 > { t ( 'about.git_integration' ) } </ h3 >
126- < p >
127- { t ( 'about.git_integration_desc1' ) }
128- </ p >
57+ { /* Left Column */ }
58+ < div style = { { display : 'flex' , flexDirection : 'column' , gap : '12px' } } >
59+ < div className = "about-card" >
60+ < h3 > { t ( 'about.what_it_is' ) } </ h3 >
61+ < p >
62+ { t ( 'about.what_it_is_desc' ) }
63+ </ p >
64+ </ div >
65+ < div className = "about-card" >
66+ < h3 > { t ( 'about.what_it_does' ) } </ h3 >
67+ < ul >
68+ < li > { t ( 'about.what_it_does_li1' ) } </ li >
69+ < li > { t ( 'about.what_it_does_li3' ) } </ li >
70+ </ ul >
71+ </ div >
72+ < div className = "about-card" >
73+ < h3 > { t ( 'about.custom_themes' ) } </ h3 >
74+ < p >
75+ { t ( 'about.custom_themes_desc1' ) }
76+ </ p >
77+ </ div >
78+ < div className = "about-card" style = { { flex : 1 , display : 'flex' , flexDirection : 'column' } } >
79+ < div style = { { display : 'flex' , gap : '1rem' , flex : 1 } } >
80+ < div style = { { flex : 1 } } >
81+ < h3 > { t ( 'about.credits' ) } </ h3 >
82+ < p >
83+ { t ( 'about.built_by' ) } < br />
84+ { t ( 'about.license' ) } < a href = "https://easyeditor.co.uk/license" target = "_blank" rel = "noopener noreferrer" > Core - Open Source (MIT)</ a > < br /> { t ( 'about.running_version' ) } < strong > { version || '...' } </ strong > < br /> { t ( 'about.available_version' ) } < strong > { availableVersion || '...' } </ strong >
85+ { version && availableVersion && compareVersions ( version , availableVersion ) < 0 && (
86+ < >
87+ < br />
88+ Latest Version: < a href = "https://github.com/gcclinux/Easyeditor/releases/latest" target = "_blank" rel = "noopener noreferrer" > Download Latest</ a >
89+ </ >
90+ ) }
91+ </ p >
92+ </ div >
93+ < div style = { { flex : 1 , borderLeft : '1px solid var(--border-color, #eee)' , paddingLeft : '1rem' } } >
94+ < h3 > { t ( 'about.powered_by' ) } </ h3 >
95+ < p >
96+ < a href = "https://mermaid.js.org/" target = "_blank" rel = "noopener noreferrer" > < b > Mermaid</ b > </ a > - { t ( 'about.official_module' ) } < br />
97+ < a href = "https://daringfireball.net/projects/markdown/" target = "_blank" rel = "noopener noreferrer" > < b > Markdown</ b > </ a > - { t ( 'about.official_module' ) } < br />
98+ < a href = "https://plantuml.com/" target = "_blank" rel = "noopener noreferrer" > < b > PlantUML</ b > </ a > - { t ( 'about.official_module' ) } < br />
99+ < a href = "https://katex.org/" target = "_blank" rel = "noopener noreferrer" > < b > KaTeX</ b > </ a > - { t ( 'about.official_module' ) }
100+ </ p >
101+ </ div >
102+ </ div >
103+ </ div >
129104 </ div >
130- < div className = "about-card" >
131- < div style = { { display : 'flex' , gap : '1rem' } } >
132- < div style = { { flex : 1 } } >
133- < h3 > { t ( 'about.credits' ) } </ h3 >
134- < p > { t ( 'about.built_by' ) } < br />
135- < span className = "muted" > { t ( 'about.last_updated' ) } { lastUpdated } </ span >
136- </ p >
137- < p > { t ( 'about.license' ) } < a href = "https://easyeditor.co.uk/license" target = "_blank" rel = "noopener noreferrer" > Core - Open Source (MIT)</ a > < br /> { t ( 'about.running_version' ) } < strong > { version || '...' } </ strong > < br /> { t ( 'about.available_version' ) } < strong > { availableVersion || '...' } </ strong >
138- { version && availableVersion && compareVersions ( version , availableVersion ) < 0 && (
139- < >
140- < br />
141- Latest Version: < a href = "https://github.com/gcclinux/Easyeditor/releases/latest" target = "_blank" rel = "noopener noreferrer" > Download Latest</ a >
142- </ >
143- ) }
105+
106+ { /* Right Column */ }
107+ < div style = { { display : 'flex' , flexDirection : 'column' , gap : '12px' } } >
108+ < div className = "about-card" >
109+ < h3 > { t ( 'about.git_integration' ) } </ h3 >
110+ < div style = { { lineHeight : '1.6' , fontSize : '0.95em' } } >
111+ < p style = { { marginBottom : '10px' } } >
112+ { t ( 'about.git_integration_desc1' ) }
144113 </ p >
145- </ div >
146- < div style = { { flex : 1 , borderLeft : '1px solid var(--border-color, #eee)' , paddingLeft : '1rem' } } >
147- < h3 > { t ( 'about.powered_by' ) } </ h3 >
148114 < p >
149- < a href = "https://mermaid.js.org/" target = "_blank" rel = "noopener noreferrer" > < b > Mermaid</ b > </ a > - { t ( 'about.official_module' ) } < br />
150- < a href = "https://daringfireball.net/projects/markdown/" target = "_blank" rel = "noopener noreferrer" > < b > Markdown</ b > </ a > - { t ( 'about.official_module' ) } < br />
151- < a href = "https://plantuml.com/" target = "_blank" rel = "noopener noreferrer" > < b > PlantUML</ b > </ a > - { t ( 'about.official_module' ) } < br />
152- < a href = "https://katex.org/" target = "_blank" rel = "noopener noreferrer" > < b > KaTeX</ b > </ a > - { t ( 'about.official_module' ) }
115+ { t ( 'about.git_integration_desc2' ) }
153116 </ p >
154117 </ div >
155118 </ div >
156- </ div >
157- < div className = "about-card" >
158- < div style = { { display : 'flex' , gap : '1rem' } } >
159- < div style = { { flex : '0 0 45%' } } >
160- < h3 > { t ( 'about.premium_features' ) } </ h3 >
161- < ul style = { { paddingLeft : '20px' , lineHeight : '1.6' , fontSize : '0.9em' } } >
162- < li > { t ( 'about.premium_features_li1' ) } </ li >
163- < li > { t ( 'about.premium_features_li2' ) } </ li >
164- < li > { t ( 'about.premium_features_li3' ) } </ li >
165- < li > { t ( 'about.premium_features_li4' ) } </ li >
166- < li > { t ( 'about.premium_features_li5' ) } </ li >
167- < li >
168- < a href = "https://climate.stripe.com/cVP4Y7" target = "_blank" rel = "noopener noreferrer" style = { { color : 'inherit' , textDecoration : 'none' } } >
169- { t ( 'about.premium_features_li6' ) } < span style = { { fontSize : '0.8em' } } > ↗</ span >
170- </ a >
171- </ li >
172- </ ul >
173- < a
174- href = "https://www.easyeditor.co.uk/#pricing"
175- target = "_blank"
176- rel = "noopener noreferrer"
177- className = "btn secondary"
178- style = { { marginTop : '5px' , padding : '6px 12px' , display : 'inline-block' , textDecoration : 'none' } }
179- >
180- View Pricing
181- </ a >
182- </ div >
183- < div style = { { flex : 1 , borderLeft : '1px solid var(--border-color, #eee)' , paddingLeft : '1rem' , minWidth : 0 } } >
184- < h3 style = { { whiteSpace : 'nowrap' } } > { t ( 'about.license_info' ) } ({ isLicenseValid && type ? type : isLicenseValid ? t ( 'about.license_premium' ) : t ( 'about.license_free' ) } )</ h3 >
185- < div style = { { display : 'flex' , flexDirection : 'column' , gap : '3px' } } >
186- < div >
187- < label style = { { display : 'block' , fontSize : '0.9em' , marginBottom : '4px' } } > { t ( 'about.license_name' ) } </ label >
188- < input
189- type = "text"
190- value = { name }
191- onChange = { ( e ) => setName ( e . target . value ) }
192- className = "license-name-input"
193- style = { { width : '95%' , padding : '4px' , borderRadius : '4px' , border : '1px solid #ccc' , color : 'red !important' } }
194- placeholder = { t ( 'about.license_name_placeholder' ) }
195- />
196- </ div >
197- < div >
198- < label style = { { display : 'block' , fontSize : '0.9em' , marginBottom : '4px' } } > { t ( 'about.license_email' ) } </ label >
199- < input
200- type = "email"
201- value = { email }
202- onChange = { ( e ) => setEmail ( e . target . value ) }
203- className = "license-email-input"
204- style = { { width : '95%' , padding : '4px' , borderRadius : '4px' , border : '1px solid #ccc' } }
205- placeholder = { t ( 'about.license_email_placeholder' ) }
206- />
207- </ div >
208- < div >
209- < label style = { { display : 'block' , fontSize : '0.9em' , marginBottom : '4px' } } > { t ( 'about.license_key' ) } </ label >
210- < input
211- type = "text"
212- value = { licenseKey }
213- onChange = { ( e ) => setLicenseKey ( e . target . value ) }
214- className = "license-key-input"
215- style = { { width : '95%' , padding : '4px' , borderRadius : '4px' , border : '1px solid #ccc' } }
216- placeholder = { t ( 'about.license_key_placeholder' ) }
217- />
218- </ div >
219- < button
220- onClick = { handleSaveLicense }
221- className = "btn secondary"
222- style = { { marginTop : '5px' , alignSelf : 'flex-start' , padding : '6px 12px' } }
223- >
224- { t ( 'about.check_license' ) }
225- </ button >
226- </ div >
119+ < div className = "about-card" style = { { flex : 1 } } >
120+ < h3 > { t ( 'about.premium_features' ) } </ h3 >
121+ < div style = { { lineHeight : '1.6' , fontSize : '0.95em' } } >
122+ < p style = { { marginBottom : '10px' } } dangerouslySetInnerHTML = { { __html : t ( 'about.premium_features_desc1' ) } } />
123+ < p style = { { marginBottom : '10px' } } dangerouslySetInnerHTML = { { __html : t ( 'about.premium_features_desc2' ) } } />
124+ < p style = { { marginBottom : '10px' } } dangerouslySetInnerHTML = { { __html : t ( 'about.premium_features_desc3' ) } } />
125+ < p dangerouslySetInnerHTML = { { __html : t ( 'about.premium_features_desc4' ) } } />
227126 </ div >
228127 </ div >
229128 </ div >
0 commit comments