Skip to content

Commit d79562b

Browse files
committed
Implement theme change in App and correct dark theme text colors
updated version and remove extra div in animated theme toggle updated version in constants and fixed overflow issue in changelog dialog.
1 parent d78e0fa commit d79562b

File tree

15 files changed

+203
-46
lines changed

15 files changed

+203
-46
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@xterm/addon-attach": "^0.11.0",
3434
"@xterm/addon-fit": "^0.10.0",
3535
"@xterm/xterm": "^5.5.0",
36+
"clsx": "^2.1.1",
3637
"file-saver": "^2.0.5",
3738
"flexlayout-react": "^0.8.1",
3839
"flowbite-react": "^0.11.7",

public/CHANGELOG.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Version 2.2.0
1+
# Version 2.0.3
22

33
#### Bluetooth support
44
<img height="10%" width="10%" src="src/assets/images/Bluetooth_FM_Black.png"/></img>

src/components/dialogs/alertdlg.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ export default function AlertDialog({ alertMessage, toggleDialog }: AlertProps)
1111
return (
1212
<div className="flex h-auto w-96 flex-col gap-2 rounded-md border border-mountain-mist-700 p-8 shadow-md transition-all dark:border-shark-500 dark:bg-shark-950">
1313
<div className="flex flex-col items-center">
14-
<h1 className="text-lg font-bold text-mountain-mist-700">
14+
<h1 className="text-lg font-bold text-mountain-mist-700 dark:text-mountain-mist-300">
1515
{t('alert')}
1616
</h1>
1717
</div>
1818
<hr className="w-full border-mountain-mist-600" />
19-
<span className='text-md text-mountain-mist-900'>{alertMessage}</span>
19+
<span className='text-md text-mountain-mist-900 dark:text-mountain-mist-300'>{alertMessage}</span>
2020
<hr className="w-full border-mountain-mist-600" />
2121
<DialogFooter
2222
hideCancelBtn={true}

src/components/dialogs/changelog.tsx

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type changelogProps = {
66
* A function to close the dialog.
77
*/
88
closeDialog: () => void;
9-
}
9+
};
1010

1111
const md = new MarkdownIt({
1212
html: true,
@@ -19,7 +19,7 @@ const md = new MarkdownIt({
1919
* ChangeLogDlg - A component that displays the changelog of the application.
2020
* @returns ChangeLogDlg
2121
*/
22-
function ChangeLogDlg({closeDialog}: changelogProps) {
22+
function ChangeLogDlg({ closeDialog }: changelogProps) {
2323
const [markdown, setMarkdown] = useState<string>('');
2424

2525
useEffect(() => {
@@ -38,39 +38,51 @@ function ChangeLogDlg({closeDialog}: changelogProps) {
3838
}, []);
3939

4040
return (
41-
<div id="default-modal" className="overflow-y-auto overflow-x-hidden justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
42-
<div className="relative w-full max-w-2xl max-h-full">
43-
<div className="relative bg-white rounded-lg shadow-sm dark:bg-gray-700">
44-
{/* Modal header */}
45-
<div className="flex items-center justify-between md:p-4 border-b rounded-t dark:border-gray-600 border-gray-200">
46-
<h3 className="text-2xl font-semibold text-gray-400 dark:text-white">
47-
Change Log
48-
</h3>
49-
<button type="button" onClick={closeDialog} className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white">
50-
<svg className="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
51-
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
52-
</svg>
53-
</button>
54-
</div>
55-
</div>
56-
{/* <hr className="w-full border-mountain-mist-600" /> */}
57-
{/* Modal body */}
58-
<div className="p-4 prose">
59-
<div className="prose prose-lg max-[767px]:prose dark:prose-invert
60-
prose-headings:font-semibold
61-
prose-h1:text-curious-blue-600 prose-h2:text-curious-blue-700 prose-h3:text-curious-blue-800
62-
prose-p:text-mountain-mist-800 prose-p:leading-relaxed
63-
prose-a:text-curious-blue-600 hover:prose-a:text-curious-blue-700
64-
prose-strong:text-mountain-mist-900
65-
prose-code:text-curious-blue-700 prose-code:bg-curious-blue-50
66-
prose-ul:my-4 prose-ol:my-4
67-
prose-li:text-mountain-mist-800">
68-
<div dangerouslySetInnerHTML={{ __html: markdown }} />
41+
<>
42+
<div
43+
id="default-modal"
44+
className="h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-hidden md:inset-0"
45+
>
46+
<div className="relative max-h-full w-full max-w-2xl">
47+
<div className="bg-white relative rounded-lg shadow-sm dark:bg-gray-700">
48+
{/* Modal header */}
49+
<div className="flex items-center justify-between rounded-t border-b border-gray-200 md:p-4 dark:border-gray-600">
50+
<h3 className="dark:text-white text-2xl font-semibold text-gray-400">
51+
Change Log
52+
</h3>
53+
<button
54+
type="button"
55+
onClick={closeDialog}
56+
className="bg-transparent dark:hover:text-white ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-600"
57+
>
58+
<svg
59+
className="h-3 w-3"
60+
aria-hidden="true"
61+
xmlns="http://www.w3.org/2000/svg"
62+
fill="none"
63+
viewBox="0 0 14 14"
64+
>
65+
<path
66+
stroke="currentColor"
67+
strokeLinecap="round"
68+
strokeLinejoin="round"
69+
strokeWidth="2"
70+
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
71+
/>
72+
</svg>
73+
</button>
74+
</div>
75+
{/* Modal body */}
76+
<div className="max-h-[85vh] overflow-y-auto overflow-x-hidden p-4">
77+
<div className="prose prose-lg max-[767px]:prose dark:prose-invert prose-headings:font-semibold prose-h1:text-curious-blue-600 prose-h2:text-curious-blue-700 prose-h3:text-curious-blue-800 prose-p:leading-relaxed prose-p:text-mountain-mist-800 prose-a:text-curious-blue-600 hover:prose-a:text-curious-blue-700 prose-strong:text-mountain-mist-900 prose-code:bg-curious-blue-50 prose-code:text-curious-blue-700 prose-ol:my-4 prose-ul:my-4 prose-li:text-mountain-mist-800 dark:prose-li:text-mountain-mist-300">
78+
<div dangerouslySetInnerHTML={{ __html: markdown }} />
79+
</div>
80+
</div>
81+
</div>
6982
</div>
7083
</div>
71-
</div>
72-
</div>
73-
)
84+
</>
85+
);
7486
}
7587

76-
export default ChangeLogDlg
88+
export default ChangeLogDlg;

src/components/dialogs/connectiondlg.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ function ConnectionDlg(connprops: ConnProps) {
4646

4747
return (
4848
<div className="border rounded-md border-mountain-mist-700 dark:border-shark-500 dark:bg-shark-950 flex h-auto w-96 flex-col items-center gap-2 p-4 shadow-md transition-all">
49-
<h1 className='text-lg font-bold text-mountain-mist-700'>{t('connections')}</h1>
50-
<p className='text-sm text-mountain-mist-700'>{t('selectConnection')}</p>
49+
<h1 className='text-lg font-bold text-mountain-mist-700 dark:text-mountain-mist-300'>{t('connections')}</h1>
50+
<p className='text-sm text-mountain-mist-700 dark:text-mountain-mist-300'>{t('selectConnection')}</p>
5151
<hr className="w-full border-mountain-mist-600" />
5252
<ul>
5353
{items.map((item) => (
@@ -57,7 +57,7 @@ function ConnectionDlg(connprops: ConnProps) {
5757
onClick={() => handleItemClick(item)}
5858
>
5959
<img data-testid={item.label} src={item.image} height="28px" width="36px" />
60-
<span>{item.label}</span>
60+
<span className='text-mountain-mist-700 dark:text-mountain-mist-300'>{item.label}</span>
6161
</li>
6262
))}
6363
</ul>

src/components/dialogs/settings.tsx

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import Button from '@/widgets/button';
77
import logger from '@/utils/logger';
88
import { CommandToXRPMgr } from '@/managers/commandstoxrpmgr';
99
import { Constants } from '@/utils/constants';
10-
import AppMgr, { EventType, LoginStatus } from '@/managers/appmgr';
10+
import AppMgr, { EventType, LoginStatus, Themes } from '@/managers/appmgr';
1111
import Login from '@/widgets/login';
1212
import { UserProfile } from '@/services/google-auth';
1313
import { fireGoogleUserTree, getUsernameFromEmail } from '@/utils/google-utils';
1414
import { useTranslation } from 'react-i18next';
1515
import TabList from '../tab-list';
1616
import TabItem from '../tab-item';
17+
import AnimatedThemeToggle from '@/widgets/animated-theme-toggle';
1718

1819
type SettingsProps = {
1920
/**
@@ -40,6 +41,8 @@ function SettingsDlg({ isXrpConnected, toggleDialog }: SettingsProps) {
4041
const [adminData, setAdminData] = useState<AdminData | undefined>(undefined);
4142
const [isValidUsername, setIsValidUsername] = useState<boolean | null>(null);
4243
const [LSXrpUser, setLSXrpUser] = useLocalStorage(StorageKeys.XRPUSER, '');
44+
const [,setTheme] = useLocalStorage(StorageKeys.THEME, Themes.LIGHT);
45+
4346
const modeLogger = logger.child({ module: 'modes' });
4447

4548
const authService = AppMgr.getInstance().authService;
@@ -325,6 +328,30 @@ function SettingsDlg({ isXrpConnected, toggleDialog }: SettingsProps) {
325328
}
326329
};
327330

331+
332+
/**
333+
* onThemeToggle - toggle theme callback
334+
* @param state
335+
*/
336+
const onThemeToggle = (state: Themes) => {
337+
// 1. Update the class for Tailwind CSS theming
338+
if (state === Themes.DARK) {
339+
document.documentElement.classList.add(Themes.DARK);
340+
document.documentElement.classList.remove(Themes.LIGHT);
341+
} else if (state === Themes.LIGHT) {
342+
document.documentElement.classList.add(Themes.LIGHT);
343+
document.documentElement.classList.remove(Themes.DARK);
344+
}
345+
setTheme(state);
346+
347+
// 2. Emit a global event to notify other components (like flexlayout)
348+
AppMgr.getInstance().setTheme(state);
349+
};
350+
351+
/**
352+
* onLoginSuccess - Google authentication callback
353+
* @param data
354+
*/
328355
const onLoginSuccess = async (data: UserProfile) => {
329356
AppMgr.getInstance().emit(EventType.EVENT_LOGIN_STATUS, LoginStatus.LOGGED_IN);
330357
const username = getUsernameFromEmail(data.email);
@@ -366,8 +393,8 @@ function SettingsDlg({ isXrpConnected, toggleDialog }: SettingsProps) {
366393
return (
367394
<div className="flex flex-col items-center gap-4 rounded-md border border-mountain-mist-700 p-8 shadow-md transition-all dark:border-shark-500 dark:bg-shark-950">
368395
<div className="flex w-[80%] flex-col items-center">
369-
<h1 className="text-lg font-bold text-mountain-mist-700">{t('settings')}</h1>
370-
<p className="text-sm text-mountain-mist-700">{t('settingDescription')}</p>
396+
<h1 className="text-lg font-bold text-mountain-mist-700 dark:text-mountain-mist-300">{t('settings')}</h1>
397+
<p className="text-sm text-mountain-mist-700 dark:text-mountain-mist-300">{t('settingDescription')}</p>
371398
</div>
372399
<hr className="w-full border-mountain-mist-600" />
373400
<TabList activeTabIndex={0}>
@@ -463,6 +490,16 @@ function SettingsDlg({ isXrpConnected, toggleDialog }: SettingsProps) {
463490
</select>
464491
</div>
465492
</TabItem>
493+
<TabItem label={t('theme.label')} isActive={false}>
494+
<div className="flex w-full flex-col gap-2 mt-2">
495+
<AnimatedThemeToggle
496+
labelLeft={t('theme.light')}
497+
labelRight={t('theme.dark')}
498+
initial={document.documentElement.classList.contains('dark')}
499+
onToggle={onThemeToggle}
500+
/>
501+
</div>
502+
</TabItem>
466503
</TabList>
467504
<hr className="w-full border-mountain-mist-600" />
468505
<DialogFooter

src/components/tab-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function TabList({ children, activeTabIndex }: TabListProps) {
3030
{tabs.map((tab, index) => (
3131
<li
3232
key={index}
33-
className={`rounded-md border-0 px-2 border-shark-400 dark:border-shark-200 text-xl hover:bg-curious-blue-400 dark:hover:bg-shark-400 ${activeTab === index ? 'text-curious-blue-600 dark:text-curious-blue-800 border-b-2 bg-mountain-mist-100 dark:bg-mountain-mist-800' : 'text-shark-300 dark:text-shark-600 bg-mountain-mist-50 dark:bg-mountain-mist-400'}`}
33+
className={`rounded-md border-0 px-2 border-shark-400 dark:border-shark-200 text-xl hover:bg-curious-blue-400 dark:hover:bg-shark-400 ${activeTab === index ? 'text-curious-blue-600 dark:text-curious-blue-800 border-b-2 bg-mountain-mist-100 dark:bg-mountain-mist-500' : 'text-shark-300 dark:text-shark-600 bg-mountain-mist-50 dark:bg-mountain-mist-400'}`}
3434
>
3535
<button
3636
key={`tab-btn-${index}`}

src/managers/appmgr.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,12 @@ export default class AppMgr {
133133
this.onThemeChange(window.matchMedia('(prefers-color-scheme: dark)').matches ? Themes.DARK : Themes.LIGHT);
134134
// listen to system theme change event
135135
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => this.onThemeChange(e.matches ? Themes.DARK : Themes.LIGHT));
136-
this._connectionMgr = new connecionMgr(this);
136+
this._connectionMgr = new connecionMgr(this);
137+
const themeFromLocalStorage = localStorage.getItem('Theme')?.replace(/"/g, '');
138+
if (themeFromLocalStorage) {
139+
this.onThemeChange(themeFromLocalStorage);
140+
this._theme = themeFromLocalStorage;
141+
}
137142
}
138143

139144
/**
@@ -152,9 +157,13 @@ export default class AppMgr {
152157
if (theme === Themes.DARK) {
153158
this._theme = Themes.DARK;
154159
this._emitter.emit(EventType.EVENT_THEME, this._theme);
160+
document.documentElement.classList.add(theme)
161+
document.documentElement.classList.remove(Themes.LIGHT);
155162
} else {
156163
this._theme = Themes.LIGHT;
157164
this._emitter.emit(EventType.EVENT_THEME, this._theme);
165+
document.documentElement.classList.add(theme)
166+
document.documentElement.classList.remove(Themes.DARK);
158167
}
159168
}
160169

@@ -166,6 +175,15 @@ export default class AppMgr {
166175
return this._theme || Themes.LIGHT;
167176
}
168177

178+
/**
179+
* setTheme
180+
* @param theme
181+
*/
182+
public setTheme(theme: Themes): void {
183+
this._theme = theme;
184+
this._emitter.emit(EventType.EVENT_THEME, this._theme);
185+
}
186+
169187
/**
170188
* Subscribe to events
171189
* @param eventName

src/utils/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export class Constants {
2-
static readonly APP_VERSION = '2.0.1';
2+
static readonly APP_VERSION = '2.0.3';
33
static readonly EDITOR_TABSET_ID = 'editorTabSetId';
44
static readonly SHELL_TABSET_ID = 'shellTabSetId';
55
static readonly SHELL_TAB_ID = 'shellTabId';

0 commit comments

Comments
 (0)