Skip to content

Commit 4a524ea

Browse files
author
Akos Kitta
committed
feat: removed the non official themes from the UI
Closes #1283 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 454802b commit 4a524ea

File tree

3 files changed

+175
-4
lines changed

3 files changed

+175
-4
lines changed

Diff for: arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx

+35-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ import {
2424
} from '@theia/core/lib/common/i18n/localization';
2525
import SettingsStepInput from './settings-step-input';
2626
import { InterfaceScale } from '../../contributions/interface-scale';
27+
import {
28+
userConfigurableThemes,
29+
contributedThemeLabel,
30+
isBuiltInTheme,
31+
} from '../../theia/core/theming';
2732

2833
const maxScale = InterfaceScale.ZoomLevel.toPercentage(
2934
InterfaceScale.ZoomLevel.MAX
@@ -218,11 +223,11 @@ export class SettingsComponent extends React.Component<
218223
<div className="flex-line">
219224
<select
220225
className="theia-select"
221-
value={this.props.themeService.getCurrentTheme().label}
226+
value={this.currentThemeLabel}
222227
onChange={this.themeDidChange}
223228
>
224-
{this.props.themeService.getThemes().map(({ id, label }) => (
225-
<option key={id} value={label}>
229+
{this.themeSelectOptions.map(({ key, label }) => (
230+
<option key={key} value={label}>
226231
{label}
227232
</option>
228233
))}
@@ -333,6 +338,30 @@ export class SettingsComponent extends React.Component<
333338
);
334339
}
335340

341+
/**
342+
* The label of the currently selected theme if it's a built-in one. Otherwise, the value of the `#contributedThemeLabel`.
343+
*/
344+
private get currentThemeLabel(): string {
345+
const currentTheme = this.props.themeService.getCurrentTheme();
346+
return isBuiltInTheme(currentTheme)
347+
? currentTheme.label
348+
: contributedThemeLabel;
349+
}
350+
351+
/**
352+
* Returns with an array of built-in theme ID/label pairs.
353+
* If the currently selected theme is a 3rd party theme,
354+
* an additional element is added to the end of the result
355+
* array with the ID of the current 3rd party theme as the
356+
* key and the value of the `#contributedThemeLabel` as the label.
357+
*/
358+
private get themeSelectOptions(): { key: string; label: string }[] {
359+
return userConfigurableThemes(this.props.themeService).map((theme) => ({
360+
key: theme.id,
361+
label: isBuiltInTheme(theme) ? theme.label : contributedThemeLabel,
362+
}));
363+
}
364+
336365
private toSelectOptions(language: string | LanguageInfo): JSX.Element {
337366
const plain = typeof language === 'string';
338367
const key = plain ? language : language.languageId;
@@ -610,7 +639,9 @@ export class SettingsComponent extends React.Component<
610639
event: React.ChangeEvent<HTMLSelectElement>
611640
): void => {
612641
const { selectedIndex } = event.target.options;
613-
const theme = this.props.themeService.getThemes()[selectedIndex];
642+
const theme = userConfigurableThemes(this.props.themeService)[
643+
selectedIndex
644+
];
614645
if (theme) {
615646
this.setState({ themeId: theme.id });
616647
if (this.props.themeService.getCurrentTheme().id !== theme.id) {

Diff for: arduino-ide-extension/src/browser/theia/core/theming.ts

+59
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import {
2+
BuiltinThemeProvider,
3+
ThemeService,
4+
} from '@theia/core/lib/browser/theming';
5+
import { nls } from '@theia/core/lib/common/nls';
16
import type { Theme } from '@theia/core/lib/common/theme';
27
import { injectable } from '@theia/core/shared/inversify';
38
import { ThemeServiceWithDB as TheiaThemeServiceWithDB } from '@theia/monaco/lib/browser/monaco-indexed-db';
@@ -17,10 +22,64 @@ export namespace ArduinoThemes {
1722
};
1823
}
1924

25+
const builtInThemeIds = new Set(
26+
[
27+
ArduinoThemes.Light,
28+
ArduinoThemes.Dark,
29+
BuiltinThemeProvider.hcTheme,
30+
// TODO: add the HC light theme after Theia 1.36
31+
].map(({ id }) => id)
32+
);
33+
export function isBuiltInTheme(theme: Theme | string): boolean {
34+
const themeId = typeof theme === 'string' ? theme : theme.id;
35+
return builtInThemeIds.has(themeId);
36+
}
37+
38+
export const contributedThemeLabel = nls.localize(
39+
'arduino/theme/contributedTheme',
40+
'Contributed Theme'
41+
);
42+
2043
@injectable()
2144
export class ThemeServiceWithDB extends TheiaThemeServiceWithDB {
2245
protected override init(): void {
2346
this.register(ArduinoThemes.Light, ArduinoThemes.Dark);
2447
super.init();
2548
}
2649
}
50+
51+
interface ThemeProvider {
52+
themes(): Theme[];
53+
currentTheme(): Theme;
54+
}
55+
56+
/**
57+
* Returns with a list of built-in themes officially supported by IDE2 (https://github.com/arduino/arduino-ide/issues/1283).
58+
* If the `currentTheme` is not a built-in one, it will be appended to the array. Built-in themes come first, followed by any contributed one.
59+
*/
60+
export function userConfigurableThemes(service: ThemeService): Theme[];
61+
export function userConfigurableThemes(provider: ThemeProvider): Theme[];
62+
export function userConfigurableThemes(
63+
serviceOrProvider: ThemeService | ThemeProvider
64+
): Theme[] {
65+
const provider =
66+
serviceOrProvider instanceof ThemeService
67+
? {
68+
currentTheme: () => serviceOrProvider.getCurrentTheme(),
69+
themes: () => serviceOrProvider.getThemes(),
70+
}
71+
: serviceOrProvider;
72+
const currentTheme = provider.currentTheme();
73+
return provider
74+
.themes()
75+
.map((theme, index) => ({ ...theme, index }))
76+
.filter((theme) => isBuiltInTheme(theme) || currentTheme.id === theme.id)
77+
.sort((left, right) => {
78+
const leftBuiltIn = isBuiltInTheme(left);
79+
const rightBuiltIn = isBuiltInTheme(right);
80+
if (leftBuiltIn === rightBuiltIn) {
81+
return left.index - right.index;
82+
}
83+
return leftBuiltIn ? -1 : 1;
84+
});
85+
}
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
2+
const disableJSDOM = enableJSDOM();
3+
4+
import { BuiltinThemeProvider } from '@theia/core/lib/browser/theming';
5+
import { Theme } from '@theia/core/lib/common/theme';
6+
import { expect } from 'chai';
7+
import {
8+
ArduinoThemes,
9+
isBuiltInTheme,
10+
userConfigurableThemes,
11+
} from '../../browser/theia/core/theming';
12+
13+
disableJSDOM();
14+
15+
const testTheme: Theme = {
16+
id: 'testTheme',
17+
label: 'Test Theme',
18+
type: 'light',
19+
};
20+
const anotherTestTheme: Theme = {
21+
id: 'anotherTestTheme',
22+
label: 'Another Test Theme',
23+
type: 'dark',
24+
};
25+
26+
describe('theming', () => {
27+
describe('userConfigurableThemes', () => {
28+
it('if the current theme is a built-in theme, the result does not contain any contributed theme', () => {
29+
const actual = userConfigurableThemes({
30+
themes: () => [
31+
ArduinoThemes.Light,
32+
ArduinoThemes.Dark,
33+
testTheme,
34+
BuiltinThemeProvider.hcTheme,
35+
anotherTestTheme,
36+
],
37+
currentTheme: () => BuiltinThemeProvider.hcTheme,
38+
});
39+
expect(actual.length).to.be.equal(3);
40+
expect(actual[0].id).to.be.equal(ArduinoThemes.Light.id);
41+
expect(actual[1].id).to.be.equal(ArduinoThemes.Dark.id);
42+
expect(actual[2].id).to.be.equal(BuiltinThemeProvider.hcTheme.id);
43+
});
44+
45+
it('if the currently selected theme is a contributed one, it is the last element in the array', () => {
46+
const actual = userConfigurableThemes({
47+
themes: () => [
48+
BuiltinThemeProvider.hcTheme,
49+
ArduinoThemes.Dark,
50+
ArduinoThemes.Light,
51+
testTheme,
52+
anotherTestTheme,
53+
],
54+
currentTheme: () => testTheme,
55+
});
56+
expect(actual.length).to.be.equal(4);
57+
expect(actual[0].id).to.be.equal(BuiltinThemeProvider.hcTheme.id);
58+
expect(actual[1].id).to.be.equal(ArduinoThemes.Dark.id);
59+
expect(actual[2].id).to.be.equal(ArduinoThemes.Light.id);
60+
expect(actual[3].id).to.be.equal(testTheme.id);
61+
});
62+
});
63+
64+
describe('isBuiltInTheme', () => {
65+
(
66+
[
67+
[BuiltinThemeProvider.lightTheme, false],
68+
[BuiltinThemeProvider.darkTheme, false],
69+
[BuiltinThemeProvider.hcTheme, true],
70+
[ArduinoThemes.Light, true],
71+
[ArduinoThemes.Dark, true],
72+
[testTheme, false],
73+
] as [Theme, boolean][]
74+
).map(([theme, expected]) =>
75+
it(`should${expected ? '' : ' not'} treat '${
76+
theme.id
77+
}' theme as built-in`, () =>
78+
expect(isBuiltInTheme(theme)).to.be.equal(expected))
79+
);
80+
});
81+
});

0 commit comments

Comments
 (0)