Skip to content

Commit ddcd8d6

Browse files
Theming - settings and view update (#29)
* Add Theme-related strings to localization resources * Implement theme in database storage * Add Theme selection to settings panel * Implement theming as ThemedView with source of truth * Apply theming to background and elements of app * Correct colors of app title buttons
1 parent 2f7d6d2 commit ddcd8d6

13 files changed

Lines changed: 283 additions & 121 deletions

File tree

src/CreateNotePanel.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from 'react-native';
1515
import Colors from './Resources/Colors';
1616
import * as dict from './Resources/Dictionary';
17+
import * as theming from './Resources/Theming/ThemeHOC';
1718

1819
interface Props {}
1920

@@ -72,7 +73,7 @@ class CreateNotePanel extends React.Component<Props, State> {
7273

7374
render() {
7475
return (
75-
<View style={styles.mainPanel}>
76+
<theming.ThemedView style={styles.mainPanel}>
7677
<TextInput
7778
style={styles.titleBox}
7879
onChangeText={this.titleOnChange}
@@ -102,7 +103,7 @@ class CreateNotePanel extends React.Component<Props, State> {
102103
onPress={this.createButtonPressed}
103104
/>
104105
</View>
105-
</View>
106+
</theming.ThemedView>
106107
);
107108
}
108109
}
@@ -112,7 +113,6 @@ const styles = StyleSheet.create({
112113
flex: 1,
113114
flexDirection: 'column',
114115
alignItems: 'center',
115-
margin: 30,
116116
},
117117
titleBox: {
118118
borderLeftWidth: 0,
@@ -122,6 +122,7 @@ const styles = StyleSheet.create({
122122
width: '90%',
123123
borderColor: Colors.noteTextPanelBorder,
124124
fontWeight: 'bold',
125+
marginTop: 30,
125126
},
126127
noteMessageBox: {
127128
borderWidth: 0.2,

src/NoteWidgetDetailsPanel.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from 'react-native';
1515
import Colors from './Resources/Colors';
1616
import * as dictionary from './Resources/Dictionary';
17+
import * as theming from './Resources/Theming/ThemeHOC';
1718

1819
interface Props {}
1920

@@ -134,7 +135,7 @@ class NoteWidgetDetailsPanel extends React.Component<Props, State> {
134135

135136
render() {
136137
return (
137-
<View style={styles.mainPanel}>
138+
<theming.ThemedView style={styles.mainPanel}>
138139
<TextInput
139140
style={styles.titleBox}
140141
onChangeText={this.titleOnChange}
@@ -148,7 +149,7 @@ class NoteWidgetDetailsPanel extends React.Component<Props, State> {
148149
/>
149150

150151
<TextInput
151-
style={styles.noteMessageBox}
152+
style={theming.applyTheming(styles.noteMessageBox)}
152153
multiline={true}
153154
onChangeText={this.messageOnChange}
154155
value={this.state.message}
@@ -178,7 +179,7 @@ class NoteWidgetDetailsPanel extends React.Component<Props, State> {
178179
onPress={this.deleteButtonPressed}
179180
/>
180181
</View>
181-
</View>
182+
</theming.ThemedView>
182183
);
183184
}
184185
}
@@ -188,14 +189,14 @@ const styles = StyleSheet.create({
188189
flex: 1,
189190
flexDirection: 'column',
190191
alignItems: 'center',
191-
margin: 30,
192192
backgroundColor: Colors.transparent,
193193
},
194194
titleBox: {
195195
borderLeftWidth: 0,
196196
borderRightWidth: 0,
197197
borderBottomWidth: 1,
198198
borderTopWidth: 0,
199+
marginTop: 40,
199200
width: '90%',
200201
borderColor: Colors.noteTextPanelBorder,
201202
fontWeight: 'bold',

src/NotesMainPanel.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import {
1111
NativeModules,
1212
StyleSheet,
1313
Text,
14-
View,
1514
} from 'react-native';
1615
import NoteWidget from './Widgets/NoteWidget';
1716
import Colors from './Resources/Colors';
1817
import Dictionary from './Resources/Dictionary';
18+
import * as theming from './Resources/Theming/ThemeHOC';
1919

2020
const noteWidgetWidth = 300;
2121

@@ -74,7 +74,7 @@ class NotesMainPanel extends React.Component<Props, State> {
7474

7575
renderWelcomePage = () => {
7676
return (
77-
<View style={styles.welcomePage}>
77+
<theming.ThemedView style={styles.welcomePage}>
7878
<Text style={styles.logoText}>ReactNativeNotes</Text>
7979
<Dictionary
8080
textLabel={'mainAppScreen.introductionTextUpper'}
@@ -85,13 +85,13 @@ class NotesMainPanel extends React.Component<Props, State> {
8585
textLabel={'mainAppScreen.introductionTextLower'}
8686
style={styles.introductionText}
8787
/>
88-
</View>
88+
</theming.ThemedView>
8989
);
9090
};
9191

9292
renderNotesPage = () => {
9393
return (
94-
<View style={styles.mainContainer}>
94+
<theming.ThemedView style={styles.mainContainer}>
9595
<FlatList<INote>
9696
key={this.state.columns}
9797
numColumns={this.state.columns}
@@ -105,7 +105,7 @@ class NotesMainPanel extends React.Component<Props, State> {
105105
/>
106106
)}
107107
/>
108-
</View>
108+
</theming.ThemedView>
109109
);
110110
};
111111

src/Resources/Localization/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@
2323
"alert.ok": "OK",
2424
"alert.noteDeleteConfirmation": "Are you sure?",
2525
"alert.noteDeletionConfirmExplanation": "Deleting the note cannot be reversed...",
26-
"alert.delete": "Delete"
26+
"alert.delete": "Delete",
27+
"theme.default": "Default",
28+
"theme.dark": "Dark",
29+
"theme.theme": "Theme:"
2730
}

src/Resources/Localization/pl.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
"alert.ok": "OK",
2424
"alert.noteDeleteConfirmation": "Jesteś pewien?",
2525
"alert.noteDeletionConfirmExplanation": "Usunięcie notatki jest nieodwracalne...",
26-
"alert.delete": "Usuń"
26+
"alert.delete": "Usuń",
27+
"theme.default": "Domyślny",
28+
"theme.dark": "Ciemny",
29+
"theme.theme": "Motyw:"
2730
}
2831

src/Resources/Theming/ThemeHOC.tsx

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React from 'react';
2+
import {NativeModules, View} from 'react-native';
3+
4+
interface Props {
5+
style: any;
6+
}
7+
8+
interface State {
9+
themeValue: number;
10+
style: any;
11+
}
12+
13+
export function applyTheming(style: any) {
14+
let theme = 0;
15+
const getTheme = async () => {
16+
await NativeModules.Database.getThemeValue()
17+
.then((result: number) => {
18+
theme = result;
19+
return result;
20+
})
21+
.catch((error: Error) => {
22+
console.log(`ERROR: ${error.message}`);
23+
});
24+
};
25+
26+
getTheme();
27+
switch (theme) {
28+
case 0:
29+
return {...style, backgroundColor: 'transparent'};
30+
case 1:
31+
return {...style, backgroundColor: '454859', color: 'white'};
32+
}
33+
}
34+
35+
export class ThemedView extends React.Component<Props, State> {
36+
constructor(props: Props) {
37+
super(props);
38+
39+
this.state = {
40+
themeValue: 0,
41+
style: props.style,
42+
};
43+
}
44+
45+
requireTheming = (style: any) => {
46+
const getTheme = async () => {
47+
await NativeModules.Database.getThemeValue()
48+
.then((result: number) => {
49+
this.setState({themeValue: result});
50+
return result;
51+
})
52+
.catch((error: Error) => {
53+
console.log(`ERROR: ${error.message}`);
54+
});
55+
};
56+
57+
getTheme();
58+
switch (this.state.themeValue) {
59+
case 0:
60+
return {...style, backgroundColor: 'transparent'};
61+
case 1:
62+
return {...style, backgroundColor: '#454859'};
63+
}
64+
};
65+
66+
render() {
67+
return (
68+
<View style={this.requireTheming(this.state.style)}>
69+
{this.props.children}
70+
</View>
71+
);
72+
}
73+
}
74+
75+
export default ThemedView;

src/SettingsPanel.tsx

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,22 @@ import React from 'react';
66
import {AppRegistry, StyleSheet, View, NativeModules} from 'react-native';
77
import {Picker} from 'react-native-windows';
88
import Colors from './Resources/Colors';
9-
import Dictionary from './Resources/Dictionary';
9+
import * as dictionary from './Resources/Dictionary';
10+
import * as theming from './Resources/Theming/ThemeHOC';
1011

1112
interface Properties {}
1213

1314
interface State {
1415
selectedLanguage: number;
16+
selectedTheme: number;
1517
}
1618

1719
class SettingsPanel extends React.Component<Properties, State> {
1820
constructor(props: Properties) {
1921
super(props);
2022
this.state = {
2123
selectedLanguage: 0,
24+
selectedTheme: 0,
2225
};
2326
}
2427

@@ -27,13 +30,18 @@ class SettingsPanel extends React.Component<Properties, State> {
2730
this.setState({selectedLanguage: value});
2831
};
2932

33+
themeValueChanged = (value: number) => {
34+
NativeModules.Database.setThemeValue(value);
35+
this.setState({selectedTheme: value});
36+
};
37+
3038
render() {
3139
return (
32-
<View style={styles.mainPanel}>
40+
<theming.ThemedView style={styles.mainPanel}>
3341
<View style={styles.languageField}>
34-
<Dictionary
42+
<dictionary.Dictionary
3543
style={styles.languageText}
36-
textLabel={'settings.languageLabel'}></Dictionary>
44+
textLabel={'settings.languageLabel'}></dictionary.Dictionary>
3745
<Picker
3846
selectedValue={this.state.selectedLanguage}
3947
style={styles.languageSelectionBox}
@@ -42,7 +50,25 @@ class SettingsPanel extends React.Component<Properties, State> {
4250
<Picker.Item label="Polski" value={1} />
4351
</Picker>
4452
</View>
45-
</View>
53+
<View style={styles.themeField}>
54+
<dictionary.Dictionary
55+
style={styles.languageText}
56+
textLabel={'theme.theme'}></dictionary.Dictionary>
57+
<Picker
58+
selectedValue={this.state.selectedTheme}
59+
style={styles.themeSelectionBox}
60+
onValueChange={this.themeValueChanged}>
61+
<Picker.Item
62+
label={dictionary.getTextByKey('theme.default')}
63+
value={0}
64+
/>
65+
<Picker.Item
66+
label={dictionary.getTextByKey('theme.dark')}
67+
value={1}
68+
/>
69+
</Picker>
70+
</View>
71+
</theming.ThemedView>
4672
);
4773
}
4874
}
@@ -52,7 +78,6 @@ const styles = StyleSheet.create({
5278
flex: 1,
5379
flexDirection: 'column',
5480
alignItems: 'center',
55-
margin: 30,
5681
},
5782
languageText: {
5883
fontWeight: 'bold',
@@ -66,10 +91,22 @@ const styles = StyleSheet.create({
6691
width: '50%',
6792
alignItems: 'center',
6893
},
94+
themeField: {
95+
flex: 1,
96+
flexDirection: 'row',
97+
justifyContent: 'space-around',
98+
margin: 20,
99+
width: '50%',
100+
alignItems: 'center',
101+
},
69102
languageSelectionBox: {
70103
height: 30,
71104
width: 150,
72105
},
106+
themeSelectionBox: {
107+
height: 30,
108+
width: 150,
109+
},
73110
});
74111

75112
AppRegistry.registerComponent('SettingsPanel', () => SettingsPanel);

src/ToDoListPanel.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import DateTimePicker from '@react-native-community/datetimepicker';
1515
import TaskWidget from './Widgets/TaskWidget';
1616
import Colors from './Resources/Colors';
1717
import * as dictionary from './Resources/Dictionary';
18+
import * as theming from './Resources/Theming/ThemeHOC';
1819

1920
interface Props {}
2021

@@ -70,7 +71,7 @@ class ToDoListPanel extends React.Component<Props, State> {
7071

7172
render() {
7273
return (
73-
<View style={styles.mainPanel}>
74+
<theming.ThemedView style={styles.mainPanel}>
7475
<View style={styles.flatListPanel}>
7576
<FlatList
7677
numColumns={1}
@@ -105,7 +106,7 @@ class ToDoListPanel extends React.Component<Props, State> {
105106
/>
106107
</View>
107108
</View>
108-
</View>
109+
</theming.ThemedView>
109110
);
110111
}
111112
}

0 commit comments

Comments
 (0)