diff --git a/api/Settings.php b/api/Settings.php
index f45410c..12e4347 100644
--- a/api/Settings.php
+++ b/api/Settings.php
@@ -22,13 +22,15 @@ class Settings extends RequestBase {
$videopath = $_POST['videopath'];
$tvshowpath = $_POST['tvshowpath'];
$tmdbsupport = $_POST['tmdbsupport'];
+ $darkmodeenabled = $_POST['darkmodeenabled'];
$query = "UPDATE settings SET
video_path='$videopath',
episode_path='$tvshowpath',
password='$password',
mediacenter_name='$mediacentername',
- TMDB_grabbing=$tmdbsupport
+ TMDB_grabbing=$tmdbsupport,
+ DarkMode=$darkmodeenabled
WHERE 1";
if ($this->conn->query($query) === true) {
@@ -44,12 +46,10 @@ class Settings extends RequestBase {
$result = $this->conn->query($query);
$r = mysqli_fetch_assoc($result);
- if ($r['password'] != "-1") {
- $r['passwordEnabled'] = true;
- } else {
- $r['passwordEnabled'] = false;
- }
+
+ $r['passwordEnabled'] = $r['password'] != "-1";
unset($r['password']);
+ $r['DarkMode'] = (bool)($r['DarkMode'] != '0');
echo json_encode($r);
});
}
diff --git a/database.sql b/database.sql
index ba71abd..b83c0fe 100644
--- a/database.sql
+++ b/database.sql
@@ -36,6 +36,8 @@ create table settings
episode_path varchar(255) null,
password varchar(32) default '-1' null,
mediacenter_name varchar(32) default 'OpenMediaCenter' null,
+ TMDB_grabbing tinyint null,
+ DarkMode tinyint default 0 null
PRIMARY KEY (id)
);
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index af62d60..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.nav-item {
- cursor: pointer;
-}
-
-.nav-link {
- color: rgba(255, 255, 255, .5);
- font-weight: bold;
-}
-
-.nav-link:hover {
- color: rgba(255, 255, 255, 1);
-}
diff --git a/src/App.js b/src/App.js
index 6793af3..6aba9c4 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,12 @@
import React from 'react';
-import "./App.css"
import HomePage from "./pages/HomePage/HomePage";
import RandomPage from "./pages/RandomPage/RandomPage";
+import GlobalInfos from "./GlobalInfos";
// include bootstraps css
import 'bootstrap/dist/css/bootstrap.min.css';
+import style from './App.module.css'
+
import SettingsPage from "./pages/SettingsPage/SettingsPage";
import CategoryPage from "./pages/CategoryPage/CategoryPage";
@@ -32,7 +34,9 @@ class App extends React.Component {
fetch('/api/Settings.php', {method: 'POST', body: updateRequest})
.then((response) => response.json()
.then((result) => {
- console.log(result);
+ // set theme
+ GlobalInfos.enableDarkTheme(result.DarkMode);
+
this.setState({
generalSettingsLoaded: true,
passwordsupport: result.passwordEnabled,
@@ -79,38 +83,27 @@ class App extends React.Component {
}
render() {
+ const themeStyle = GlobalInfos.getThemeStyle();
+ // add the main theme to the page body
+ document.body.className = themeStyle.backgroundcolor;
return (
-
);
diff --git a/src/App.module.css b/src/App.module.css
new file mode 100644
index 0000000..adb0857
--- /dev/null
+++ b/src/App.module.css
@@ -0,0 +1,54 @@
+.navitem {
+ float: left;
+ margin-left: 20px;
+
+ cursor: pointer;
+ opacity: 0.6;
+
+ font-size: large;
+ font-weight: bold;
+ text-transform: capitalize;
+}
+
+.navitem:hover {
+ opacity: 1;
+ transition: opacity .5s;
+}
+
+.navitem::after {
+ content: '';
+ display: block;
+ width: 0;
+ height: 2px;
+ transition: width .3s;
+}
+
+.navitem:hover::after {
+ width: 100%;
+}
+
+
+.navitemselected {
+ opacity: 0.85;
+}
+
+.navcontainer {
+ padding-top: 20px;
+ width: 100%;
+ padding-bottom: 40px;
+
+ border-width: 0;
+ border-style: dotted;
+ border-bottom-width: 2px;
+}
+
+.navbrand {
+ margin-left: 20px;
+ margin-right: 20px;
+ font-size: large;
+ font-weight: bold;
+ text-transform: capitalize;
+ float: left;
+}
+
+
diff --git a/src/App.test.js b/src/App.test.js
index e2b2d33..cc12113 100644
--- a/src/App.test.js
+++ b/src/App.test.js
@@ -10,19 +10,19 @@ describe('', function () {
it('renders title', () => {
const wrapper = shallow();
- expect(wrapper.find('.navbar-brand').text()).toBe('OpenMediaCenter');
+ expect(wrapper.find('.navbrand').text()).toBe('OpenMediaCenter');
});
it('are navlinks correct', function () {
const wrapper = shallow();
- expect(wrapper.find('nav').find('li')).toHaveLength(4);
+ expect(wrapper.find('.navitem')).toHaveLength(4);
});
it('simulate video view change ', function () {
const wrapper = shallow();
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
- wrapper.instance().changeRootElement();
+ wrapper.instance().changeRootElement();
expect(wrapper.find("#testit")).toHaveLength(1);
});
@@ -31,7 +31,7 @@ describe('', function () {
const wrapper = shallow();
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
- wrapper.instance().changeRootElement();
+ wrapper.instance().changeRootElement();
expect(wrapper.find("#testit")).toHaveLength(1);
@@ -44,9 +44,9 @@ describe('', function () {
const wrapper = shallow();
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
- wrapper.find(".nav-link").findWhere(t => t.text() === "Random Video" && t.type() === "div").simulate("click");
+ wrapper.find(".navitem").findWhere(t => t.text() === "Random Video" && t.type() === "div").simulate("click");
- wrapper.instance().changeRootElement();
+ wrapper.instance().changeRootElement();
expect(wrapper.find("#testit")).toHaveLength(1);
@@ -61,7 +61,7 @@ describe('', function () {
wrapper.setState({page: "wrongvalue"});
expect(wrapper.find("HomePage")).toHaveLength(0);
- wrapper.find(".nav-link").findWhere(t => t.text() === "Home" && t.type() === "div").simulate("click");
+ wrapper.find(".navitem").findWhere(t => t.text() === "Home" && t.type() === "div").simulate("click");
expect(wrapper.find("HomePage")).toHaveLength(1);
});
@@ -70,7 +70,7 @@ describe('', function () {
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
expect(wrapper.find("CategoryPage")).toHaveLength(0);
- wrapper.find(".nav-link").findWhere(t => t.text() === "Categories" && t.type() === "div").simulate("click");
+ wrapper.find(".navitem").findWhere(t => t.text() === "Categories" && t.type() === "div").simulate("click");
expect(wrapper.find("CategoryPage")).toHaveLength(1);
});
@@ -79,7 +79,7 @@ describe('', function () {
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
expect(wrapper.find("SettingsPage")).toHaveLength(0);
- wrapper.find(".nav-link").findWhere(t => t.text() === "Settings" && t.type() === "div").simulate("click");
+ wrapper.find(".navitem").findWhere(t => t.text() === "Settings" && t.type() === "div").simulate("click");
expect(wrapper.find("SettingsPage")).toHaveLength(1);
});
diff --git a/src/AppDarkTheme.module.css b/src/AppDarkTheme.module.css
new file mode 100644
index 0000000..d951ea9
--- /dev/null
+++ b/src/AppDarkTheme.module.css
@@ -0,0 +1,40 @@
+/**
+ * The coloring elements for dark theme
+ */
+
+.backgroundcolor {
+ background-color: #141520;
+}
+
+.textcolor {
+ color: white;
+}
+
+.subtextcolor {
+ color: #dedad6;
+}
+
+.lighttextcolor {
+ color: #d5d5d5;
+}
+
+.navitem::after {
+ background: white;
+}
+
+.hrcolor {
+ border-color: rgba(255, 255, 255, .1);
+}
+
+.secbackground {
+ background-color: #3c3d48;
+}
+
+.thirdbackground {
+ background-color: #141520;
+}
+
+.preview:hover {
+ box-shadow: rgba(255, 255, 255, 0.7) 0 0 0 5px;
+}
+
diff --git a/src/AppLightTheme.module.css b/src/AppLightTheme.module.css
new file mode 100644
index 0000000..72ace73
--- /dev/null
+++ b/src/AppLightTheme.module.css
@@ -0,0 +1,39 @@
+/**
+ * The coloring elements for light theme
+ */
+
+.navitem::after {
+ background: black;
+}
+
+.backgroundcolor {
+ background-color: white;
+}
+
+.textcolor {
+ color: black;
+}
+
+.subtextcolor {
+ color: #212529;
+}
+
+.lighttextcolor {
+ color: #3d3d3d;
+}
+
+.hrcolor {
+ border-color: rgba(0, 0, 0, 0.1);
+}
+
+.secbackground {
+ background-color: #a8c3ff;
+}
+
+.thirdbackground {
+ background-color: #8ca3fc;
+}
+
+.preview:hover {
+ box-shadow: rgba(2, 12, 27, 0.7) 0 0 0 5px;
+}
diff --git a/src/GlobalInfos.js b/src/GlobalInfos.js
new file mode 100644
index 0000000..af86c41
--- /dev/null
+++ b/src/GlobalInfos.js
@@ -0,0 +1,23 @@
+import darktheme from "./AppDarkTheme.module.css";
+import lighttheme from "./AppLightTheme.module.css";
+
+class StaticInfos {
+ #darktheme = true;
+
+ isDarkTheme() {
+ return this.#darktheme;
+ };
+
+ enableDarkTheme(enable = true){
+ this.#darktheme = enable;
+ }
+
+ getThemeStyle(){
+ return this.isDarkTheme() ? darktheme : lighttheme;
+ }
+}
+
+const GlobalInfos = new StaticInfos();
+//Object.freeze(StaticInfos);
+
+export default GlobalInfos;
diff --git a/src/GlobalInfos.test.js b/src/GlobalInfos.test.js
new file mode 100644
index 0000000..c87cf85
--- /dev/null
+++ b/src/GlobalInfos.test.js
@@ -0,0 +1,24 @@
+import React from "react";
+import GlobalInfos from "./GlobalInfos";
+
+describe('', function () {
+ it('always same instance ', function () {
+ GlobalInfos.enableDarkTheme(true);
+
+ expect(GlobalInfos.isDarkTheme()).toBe(true);
+
+ GlobalInfos.enableDarkTheme(false);
+
+ expect(GlobalInfos.isDarkTheme()).toBe(false);
+ });
+
+ it('test default theme', function () {
+ expect(GlobalInfos.isDarkTheme()).toBe(false);
+ });
+
+ it('test receive of stylesheet', function () {
+ const style = GlobalInfos.getThemeStyle();
+
+ expect(style.navitem).not.toBeNull();
+ });
+});
diff --git a/src/elements/PageTitle/PageTitle.js b/src/elements/PageTitle/PageTitle.js
index cce4ec9..a71d946 100644
--- a/src/elements/PageTitle/PageTitle.js
+++ b/src/elements/PageTitle/PageTitle.js
@@ -1,5 +1,6 @@
import React from "react";
import style from "./PageTitle.module.css"
+import GlobalInfos from "../../GlobalInfos";
class PageTitle extends React.Component {
constructor(props) {
@@ -10,17 +11,33 @@ class PageTitle extends React.Component {
}
render() {
+ const themeStyle = GlobalInfos.getThemeStyle();
return (
-
-
{this.props.title}
-
{this.props.subtitle}
+
+ {this.props.title}
+ {this.props.subtitle}
<>
{this.props.children}
>
-
+
);
}
}
-export default PageTitle;
\ No newline at end of file
+/**
+ * class to override default
color and styling
+ * use this for horizontal lines to use the current active theming
+ */
+export class Line extends React.Component {
+ render() {
+ const themeStyle = GlobalInfos.getThemeStyle();
+ return (
+ <>
+
+ >
+ );
+ }
+}
+
+export default PageTitle;
diff --git a/src/elements/PageTitle/PageTitle.module.css b/src/elements/PageTitle/PageTitle.module.css
index c2ae436..76b3fcb 100644
--- a/src/elements/PageTitle/PageTitle.module.css
+++ b/src/elements/PageTitle/PageTitle.module.css
@@ -1,8 +1,5 @@
.pageheader {
- margin-bottom: 20px;
- margin-top: 20px;
- padding-left: 22%;
- padding-right: 12%;
+ padding: 20px 12% 20px 22%;
}
.pageheadertitle {
@@ -11,7 +8,7 @@
}
.pageheadersubtitle {
- font-size: 23pt;
margin-left: 20px;
+ font-size: 23pt;
opacity: 0.6;
}
diff --git a/src/elements/PageTitle/PageTitle.test.js b/src/elements/PageTitle/PageTitle.test.js
index 5d57908..6ed16c2 100644
--- a/src/elements/PageTitle/PageTitle.test.js
+++ b/src/elements/PageTitle/PageTitle.test.js
@@ -19,7 +19,7 @@ describe('
', function () {
it('renders pagetitle prop', function () {
const wrapper = shallow(
);
- expect(wrapper.find(".pageheader").text()).toBe("testtitle");
+ expect(wrapper.find(".pageheader").text()).toBe("testtitle
");
});
it('renders subtitle prop', function () {
diff --git a/src/elements/Preview/Preview.js b/src/elements/Preview/Preview.js
index 4e31520..0a1cb5a 100644
--- a/src/elements/Preview/Preview.js
+++ b/src/elements/Preview/Preview.js
@@ -2,6 +2,7 @@ import React from "react";
import style from "./Preview.module.css";
import Player from "../../pages/Player/Player";
import {Spinner} from "react-bootstrap";
+import GlobalInfos from "../../GlobalInfos";
class Preview extends React.Component {
constructor(props, context) {
@@ -33,9 +34,10 @@ class Preview extends React.Component {
}
render() {
+ const themeStyle = GlobalInfos.getThemeStyle();
return (
-
this.itemClick()}>
-
{this.state.name}
+
this.itemClick()}>
+
{this.state.name}
{this.state.previewpicture !== null ?
this.itemClick()}>
-
+
this.itemClick()}>
+
{this.props.name}
diff --git a/src/elements/Preview/Preview.module.css b/src/elements/Preview/Preview.module.css
index 9122a92..ae23695 100644
--- a/src/elements/Preview/Preview.module.css
+++ b/src/elements/Preview/Preview.module.css
@@ -1,5 +1,6 @@
.previewtitle {
- color: #3d3d3d;
+ height: 20px;
+ text-align: center;
font-size: smaller;
font-weight: bold;
height: 20px;
@@ -33,10 +34,8 @@
}
.videopreview {
- background-color: #a8c3ff;
border-radius: 20px;
cursor: pointer;
- /*background-color: #7F7F7F;*/
float: left;
margin-left: 25px;
margin-top: 25px;
@@ -44,7 +43,6 @@
}
.videopreview:hover {
- box-shadow: rgba(2, 12, 27, 0.7) 0 0 0 5px;
opacity: 1;
transition: all 300ms;
}
diff --git a/src/elements/SideBar/SideBar.js b/src/elements/SideBar/SideBar.js
index 9375f33..1b050a8 100644
--- a/src/elements/SideBar/SideBar.js
+++ b/src/elements/SideBar/SideBar.js
@@ -1,9 +1,11 @@
import React from "react";
import style from "./SideBar.module.css"
+import GlobalInfos from "../../GlobalInfos";
class SideBar extends React.Component {
render() {
- return (
+ const themeStyle = GlobalInfos.getThemeStyle();
+ return (
{this.props.children}
);
}
@@ -11,16 +13,18 @@ class SideBar extends React.Component {
export class SideBarTitle extends React.Component {
render() {
+ const themeStyle = GlobalInfos.getThemeStyle();
return (
-
{this.props.children}
+
{this.props.children}
);
}
}
export class SideBarItem extends React.Component {
render() {
+ const themeStyle = GlobalInfos.getThemeStyle();
return (
-
{this.props.children}
+
{this.props.children}
);
}
}
diff --git a/src/elements/SideBar/SideBar.module.css b/src/elements/SideBar/SideBar.module.css
index e20342b..1ced68e 100644
--- a/src/elements/SideBar/SideBar.module.css
+++ b/src/elements/SideBar/SideBar.module.css
@@ -1,5 +1,4 @@
.sideinfo {
- background-color: #b4c7fe;
border: 2px #3574fe solid;
border-radius: 20px;
float: left;
@@ -16,7 +15,6 @@
}
.sidebarinfo {
- background-color: #8ca3fc;
border-radius: 5px;
margin-top: 5px;
padding: 2px 10px 2px 15px;
diff --git a/src/index.css b/src/index.css
deleted file mode 100644
index f2297d6..0000000
--- a/src/index.css
+++ /dev/null
@@ -1,8 +0,0 @@
-body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- margin: 0;
- -moz-osx-font-smoothing: grayscale;
-}
diff --git a/src/index.js b/src/index.js
index 88fa6af..7384bc7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,6 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import './index.css';
import App from './App';
ReactDOM.render(
diff --git a/src/pages/CategoryPage/CategoryPage.js b/src/pages/CategoryPage/CategoryPage.js
index 8ca56d1..2e26468 100644
--- a/src/pages/CategoryPage/CategoryPage.js
+++ b/src/pages/CategoryPage/CategoryPage.js
@@ -5,7 +5,7 @@ import videocontainerstyle from "../../elements/VideoContainer/VideoContainer.mo
import {TagPreview} from "../../elements/Preview/Preview";
import NewTagPopup from "../../elements/NewTagPopup/NewTagPopup";
-import PageTitle from "../../elements/PageTitle/PageTitle";
+import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
import VideoContainer from "../../elements/VideoContainer/VideoContainer";
class CategoryPage extends React.Component {
@@ -56,7 +56,7 @@ class CategoryPage extends React.Component {
this.loadTag(e.props.category)
}
}}>HD
-
+