diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1c580f7..eee496f9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ All contributions are welcome! However, there are some things you need to take note of before starting your contribution to the Mue project. ## General -Test *everything*. That's right - make sure every feature still works depending on the change you just implemented. If it's a translation, check if all strings are translated. +Test *everything*. That's right - make sure every feature still works depending on the change you just implemented. If it's a translation, check if all strings are translated. A bug fix? See if it has fixed the issue fully on both Chromium and Firefox. For features, make sure that everything else still works fine and is compatible with what you implemented. @@ -21,7 +21,7 @@ We prefer it if you implement features from our [projects board](https://github. issue or our Discord server (see README for invite). Here's a quick list of things to look out for: * External APIs - Please refrain from requesting to servers not on the ``muetab.xyz``, ``derpyenterprises.org`` or ``duckduckgo.com`` domains. Whenever possible, try to create a "proxy" API service for requests to go through. Pull requests involving paid APIs or heavily limited free plans will be denied. -* Clones - Please don't go blatantly copying features from the alternative extensions out there unless you have written permission from the original author of the project. +* Clones - Please don't go blatantly copying features from the alternative extensions out there unless you have written permission from the original author of the project. Inspired features are fine. * Removed Features - If a feature has been removed by us don't add it back again without asking us about it first for the reasons as to why it was removed in the first place. diff --git a/README.md b/README.md index f406b526..065985f0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -> Mue +> Mue [![License](https://img.shields.io/badge/license-BSD%203-blue?style=flat-square)](/LICENSE) [![Discord](https://img.shields.io/discord/659129207208804381?label=discord&color=7289DA&style=flat-square)](https://discord.gg/zv8C9F8) [![Code Size]( https://img.shields.io/github/languages/code-size/mue/mue?color=green&label=size&style=flat-square)]()
@@ -44,10 +44,10 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an * Marketplace - download custom photo packs, quote packs, preset settings and themes made by the community! ### Planned Features -Please see our [roadmap](https://github.com/mue/mue/projects/2) +Please see our [roadmap](https://github.com/mue/mue/projects) ## Installation -*A demo of the tab can be found [here](https://demo.muetab.xyz)* +*A demo of the tab can be found [here](https://demo.muetab.com)* ### Chrome [![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
@@ -132,11 +132,11 @@ Please see our [roadmap](https://github.com/mue/mue/projects/2) ### Translators [Wessel Tip](https://github.com/Wessel) - Dutch -[Alex Sparkes](https://github.com/alexsparkes) - French +[Alex Sparkes](https://github.com/alexsparkes), [Maxime](https://github.com/exiam) - French [Anders](https://github.com/FuryingFox) - Norwegian -[MrZillaGold](https://github.com/MrZillaGold) - Russian +[Pronin Egor](https://github.com/MrZillaGold) - Russian ### Other [Pexels](https://pexels.com) - Stock photos used for offline mode diff --git a/manifest/chrome.json b/manifest/chrome.json index 1d57794e..d79c7e33 100644 --- a/manifest/chrome.json +++ b/manifest/chrome.json @@ -3,7 +3,7 @@ "offline_enabled": true, "name": "Mue", "description": "Fast, open and free-to-use new tab page for most modern browsers.", - "version": "4.1.1", + "version": "4.2.1", "browser_action": { "default_icon": "icons/128x128.png" }, diff --git a/manifest/firefox.json b/manifest/firefox.json index 81304a8f..78fac847 100644 --- a/manifest/firefox.json +++ b/manifest/firefox.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "Mue", "description": "Fast, open and free-to-use new tab page for most modern browsers.", - "version": "4.1.1", + "version": "4.2.1", "browser_action": { "default_icon": "icons/128x128.png" }, diff --git a/manifest/opera.json b/manifest/opera.json index 66c30856..d8c21ad8 100644 --- a/manifest/opera.json +++ b/manifest/opera.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "Mue", "description": "Fast, open and free-to-use new tab page for most modern browsers.", - "version": "4.1.1", + "version": "4.2.0", "browser_action": { "default_icon": "icons/128x128.png" }, diff --git a/package.json b/package.json index b3f36c9c..bdef07cd 100644 --- a/package.json +++ b/package.json @@ -13,18 +13,18 @@ "homepage": "https://muetab.xyz", "bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D", "license": "BSD-3-Clause", - "version": "4.1.1", + "version": "4.2.1", "dependencies": { - "@material-ui/core": "^4.11.0", - "@material-ui/icons": "^4.9.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@muetab/quotes": "^1.0.0", - "react": "^16.13.1", + "lodash.merge": "4.6.2", + "react": "16.14.0", "react-clock": "^2.4.0", - "react-dom": "^16.13.1", - "react-modal": "^3.11.2", - "react-toastify": "^6.0.8", - "supports-webp": "^2.0.1", - "lodash.merge": "4.6.2" + "react-dom": "16.14.0", + "react-modal": "3.11.2", + "react-toastify": "6.0.9", + "supports-webp": "2.0.1" }, "devDependencies": { "react-scripts": "3.4.3", diff --git a/public/offline-images/1.jpeg b/public/offline-images/1.jpg similarity index 100% rename from public/offline-images/1.jpeg rename to public/offline-images/1.jpg diff --git a/public/offline-images/10.jpeg b/public/offline-images/10.jpg similarity index 100% rename from public/offline-images/10.jpeg rename to public/offline-images/10.jpg diff --git a/public/offline-images/11.jpeg b/public/offline-images/11.jpg similarity index 100% rename from public/offline-images/11.jpeg rename to public/offline-images/11.jpg diff --git a/public/offline-images/12.jpeg b/public/offline-images/12.jpg similarity index 100% rename from public/offline-images/12.jpeg rename to public/offline-images/12.jpg diff --git a/public/offline-images/13.jpeg b/public/offline-images/13.jpg similarity index 100% rename from public/offline-images/13.jpeg rename to public/offline-images/13.jpg diff --git a/public/offline-images/14.jpeg b/public/offline-images/14.jpg similarity index 100% rename from public/offline-images/14.jpeg rename to public/offline-images/14.jpg diff --git a/public/offline-images/15.jpeg b/public/offline-images/15.jpg similarity index 100% rename from public/offline-images/15.jpeg rename to public/offline-images/15.jpg diff --git a/public/offline-images/16.jpeg b/public/offline-images/16.jpg similarity index 100% rename from public/offline-images/16.jpeg rename to public/offline-images/16.jpg diff --git a/public/offline-images/17.jpeg b/public/offline-images/17.jpg similarity index 100% rename from public/offline-images/17.jpeg rename to public/offline-images/17.jpg diff --git a/public/offline-images/18.jpeg b/public/offline-images/18.jpg similarity index 100% rename from public/offline-images/18.jpeg rename to public/offline-images/18.jpg diff --git a/public/offline-images/19.jpeg b/public/offline-images/19.jpg similarity index 100% rename from public/offline-images/19.jpeg rename to public/offline-images/19.jpg diff --git a/public/offline-images/2.jpeg b/public/offline-images/2.jpg similarity index 100% rename from public/offline-images/2.jpeg rename to public/offline-images/2.jpg diff --git a/public/offline-images/20.jpeg b/public/offline-images/20.jpg similarity index 100% rename from public/offline-images/20.jpeg rename to public/offline-images/20.jpg diff --git a/public/offline-images/3.jpeg b/public/offline-images/3.jpg similarity index 100% rename from public/offline-images/3.jpeg rename to public/offline-images/3.jpg diff --git a/public/offline-images/4.jpeg b/public/offline-images/4.jpg similarity index 100% rename from public/offline-images/4.jpeg rename to public/offline-images/4.jpg diff --git a/public/offline-images/5.jpeg b/public/offline-images/5.jpg similarity index 100% rename from public/offline-images/5.jpeg rename to public/offline-images/5.jpg diff --git a/public/offline-images/6.jpeg b/public/offline-images/6.jpg similarity index 100% rename from public/offline-images/6.jpeg rename to public/offline-images/6.jpg diff --git a/public/offline-images/7.jpeg b/public/offline-images/7.jpg similarity index 100% rename from public/offline-images/7.jpeg rename to public/offline-images/7.jpg diff --git a/public/offline-images/8.jpeg b/public/offline-images/8.jpg similarity index 100% rename from public/offline-images/8.jpeg rename to public/offline-images/8.jpg diff --git a/public/offline-images/9.jpeg b/public/offline-images/9.jpg similarity index 100% rename from public/offline-images/9.jpeg rename to public/offline-images/9.jpg diff --git a/src/App.jsx b/src/App.jsx index 934baf53..d5340b93 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -16,11 +16,9 @@ import Modal from 'react-modal'; import merge from 'lodash.merge'; import RoomIcon from '@material-ui/icons/Room'; -// Modals are lazy loaded as a user won't use them every time they open a tab -const Settings = React.lazy(() => import('./components/modals/Settings')); +// Modals are lazy loaded as the user won't use them every time they open a tab +const MainModal = React.lazy(() => import('./components/modals/MainModal')); const Update = React.lazy(() => import('./components/modals/Update')); -const Marketplace = React.lazy(() => import('./components/modals/Marketplace')); -const Addons = React.lazy(() => import('./components/modals/Addons')); //const Welcome = React.lazy(() => import('./components/modals/Welcome')); const renderLoader = () =>
; @@ -28,12 +26,8 @@ export default class App extends React.PureComponent { constructor(props) { super(props); this.state = { - settingsModal: false, - updateModal: false, - marketplaceModal: false, - addonsModal: false, - quickAccessmodal: false, - welcomeModal: false + mainModal: false, + updateModal: false }; } @@ -41,7 +35,12 @@ export default class App extends React.PureComponent { render() { if (!localStorage.getItem('firstRun')) SettingsFunctions.setDefaultSettings(); - const modalClassList = (localStorage.getItem('darkTheme') === 'true') ? 'Modal dark' : 'Modal'; // Modal features + let modalClassList = 'Modal'; // Modal features + let tooltipClassList = 'tooltiptext'; + if ((localStorage.getItem('brightnessTime') && new Date().getHours() > 18) || localStorage.getItem('darkTheme') === 'true') { + modalClassList = 'Modal dark'; + tooltipClassList = 'tooltiptext dark'; + } const overlayClassList = (localStorage.getItem('animations') === 'true') ? 'Overlay modal-animation' : 'Overlay'; const en = require('./translations/en.json'); // User language @@ -58,10 +57,10 @@ export default class App extends React.PureComponent { return ( - +
- this.setState({ settingsModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} /> + this.setState({ mainModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} /> @@ -70,46 +69,22 @@ export default class App extends React.PureComponent {
- +
- this.setState({ settingsModal: false })} isOpen={this.state.settingsModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> - this.setState({ settingsModal: false })} - setDefaultSettings={() => SettingsFunctions.setDefaultSettings()} - openMarketplace={() => this.setState({ marketplaceModal: true, settingsModal: false })} - openAddons={() => this.setState({ settingsModal: false, addonsModal: true })} - toastLanguage={language.toasts} /> + this.setState({ mainModal: false })} isOpen={this.state.mainModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> + this.setState({ mainsModal: false })} /> this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> this.setState({ updateModal: false })} /> - this.setState({ marketplaceModal: false })} isOpen={this.state.marketplaceModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}> - this.setState({ marketplaceModal: false })} - openSettings={() => this.setState({ marketplaceModal: false, settingsModal: true })} - openAddons={() => this.setState({ marketplaceModal: false, addonsModal: true })} - toastLanguage={language.toasts} /> - - this.setState({ addonsModal: false })} isOpen={this.state.addonsModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}> - this.setState({ addonsModal: false })} - openSettings={() => this.setState({ addonsModal: false, settingsModal: true })} - openMarketplace={() => this.setState({ addonsModal: false, marketplaceModal: true })} - toastLanguage={language.toasts} /> - {/* this.setState({ welcomeModal: false })} isOpen={this.state.welcomeModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}> this.setState({ welcomeModal: false })} /> */ } diff --git a/src/components/modals/MainModal.jsx b/src/components/modals/MainModal.jsx new file mode 100644 index 00000000..095ac294 --- /dev/null +++ b/src/components/modals/MainModal.jsx @@ -0,0 +1,74 @@ +import React from 'react'; + +import Settings from './tabs/Settings'; +import Addons from './tabs/Addons'; +import Marketplace from './tabs/Marketplace'; + +export default class MainModal extends React.PureComponent { + constructor(...args) { + super(...args); + this.state = { + tab: , + settingsActive: 'active', + addonsActive: '', + marketplaceActive: '' + }; + } + + componentDidMount() { + document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); + document.getElementById('center').classList.toggle('backgroundEffects'); + } + + componentWillUnmount() { + document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); + document.getElementById('center').classList.toggle('backgroundEffects'); + } + + changeEnabled(input) { + switch (input) { + case 'addons': + this.setState({ + tab: this.changeEnabled('marketplace')}/>, + addonsActive: 'active', + settingsActive: '', + marketplaceActive: '' + }); + break; + case 'settings': + this.setState({ + tab: , + settingsActive: 'active', + addonsActive: '', + marketplaceActive: '' + }); + break; + case 'marketplace': + this.setState({ + tab: , + marketplaceActive: 'active', + addonsActive: '', + settingsActive: '' + }); + break; + default: + break; + } + } + + render() { + return ( +
+ × +

{this.props.language.modals.title}

+
+ + + +
+
+ {this.state.tab} +
+ ) + } +} \ No newline at end of file diff --git a/src/components/modals/marketplace/Items.jsx b/src/components/modals/marketplace/Items.jsx index e030c545..c861df3d 100644 --- a/src/components/modals/marketplace/Items.jsx +++ b/src/components/modals/marketplace/Items.jsx @@ -2,8 +2,10 @@ import React from 'react'; export default class Items extends React.PureComponent { render() { + if (this.props.items.length === 0) return null; + let seeMoreHTML; - if (this.props.seeMoreFunction) seeMoreHTML = ; + if (this.props.seeMoreFunction && this.props.items.length === 3) seeMoreHTML = ; return (
@@ -11,7 +13,7 @@ export default class Items extends React.PureComponent {

{this.props.title}

{this.props.items.map((item) => -
this.props.toggleFunction(item.name)}> +
this.props.toggleFunction(item.name)} key={item.name}> icon

{item.display_name}

diff --git a/src/components/modals/settings/Checkbox.jsx b/src/components/modals/settings/Checkbox.jsx index 9a5ea2e1..d729fd58 100644 --- a/src/components/modals/settings/Checkbox.jsx +++ b/src/components/modals/settings/Checkbox.jsx @@ -17,11 +17,14 @@ export default class Checkbox extends React.PureComponent { } render() { + let text = this.props.text; + if (this.props.newFeature) text = {this.props.text} NEW; + return ( this.handleChange(this.props.name)} />} - label={this.props.text} + label={text} />
diff --git a/src/components/modals/settings/Section.jsx b/src/components/modals/settings/Section.jsx index bf127e24..7b71cab5 100644 --- a/src/components/modals/settings/Section.jsx +++ b/src/components/modals/settings/Section.jsx @@ -22,7 +22,7 @@ export default class Section extends React.PureComponent { } render() { - let extraHTML, expandMore, slider; + let extraHTML, expandMore, slider, noDropdown; if (this.props.children) { extraHTML =
  • {this.props.children}
  • expandMore = ; + if (this.props.noDropdown) noDropdown = 'nodropdown'; return (
    -

    this.toggleSection()}>{this.props.title}

    +

    this.toggleSection()}>{this.props.title}

    {expandMore} {slider}
    diff --git a/src/components/modals/settings/sections/BackgroundSettings.jsx b/src/components/modals/settings/sections/BackgroundSettings.jsx index d36c020b..dae31f65 100644 --- a/src/components/modals/settings/sections/BackgroundSettings.jsx +++ b/src/components/modals/settings/sections/BackgroundSettings.jsx @@ -1,8 +1,10 @@ import React from 'react'; import { toast } from 'react-toastify'; +import Checkbox from '../Checkbox'; +import Section from '../Section'; export default class BackgroundSettings extends React.PureComponent { - DefaultGradientSettings = { "angle": "180", "gradient": [{ "colour": "Disabled", "stop": 0 }], "type": "linear" }; + DefaultGradientSettings = { "angle": "180", "gradient": [{ "colour": this.props.language.background.disabled, "stop": 0 }], "type": "linear" }; constructor(...args) { super(...args); @@ -117,14 +119,14 @@ export default class BackgroundSettings extends React.PureComponent { } currentGradientSettings = () => { - if (typeof this.state.gradientSettings === 'object' && this.state.gradientSettings.gradient.every(g => g.colour !== 'Disabled')) { + if (typeof this.state.gradientSettings === 'object' && this.state.gradientSettings.gradient.every(g => g.colour !== this.props.language.background.disabled)) { const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); return JSON.stringify({ ...this.state.gradientSettings, gradient: [...this.state.gradientSettings.gradient.map(g => { return { ...g, stop: clampNumber(+g.stop, 0, 100) } })].sort((a, b) => (a.stop > b.stop) ? 1 : -1) }); } - return 'Disabled'; + return this.props.language.background.disabled; } render() { @@ -145,44 +147,51 @@ export default class BackgroundSettings extends React.PureComponent { colourSettings = (
    {gradientInputs} - {this.state.gradientSettings.gradient[0].colour !== 'Disabled' ? () : null} + {this.state.gradientSettings.gradient[0].colour !== this.props.language.background.disabled ? () : null}
    ); } return ( -
    -
      - - -
    -
      -

      {this.props.language.background.blur} ({this.state.blur}%) this.resetItem('blur')}>{this.props.language.reset}

      - this.setState({ blur: event.target.value })} /> -
    -
      -

      {this.props.language.background.brightness} ({this.state.brightness}%) this.resetItem('brightness')}>{this.props.language.reset}

      - this.setState({ brightness: event.target.value })} /> -
    -
      -

      {this.props.language.background.customURL} this.resetItem('customBackground')}>{this.props.language.reset}

      - -
    -
      -

      {this.props.language.background.custombackground} this.resetItem('customBackground')}>{this.props.language.reset}

      - - -
    -
      -

      {this.props.language.background.customcolour} this.resetItem('customBackgroundColour')}>{this.props.language.reset}

      - - {colourSettings} -
    -
    + +
    +
      + + + +
    +
      + + +
    +
      +

      {this.props.language.background.blur} ({this.state.blur}%) this.resetItem('blur')}>{this.props.language.reset}

      + this.setState({ blur: event.target.value })} /> +
    +
      +

      {this.props.language.background.brightness} ({this.state.brightness}%) this.resetItem('brightness')}>{this.props.language.reset}

      + this.setState({ brightness: event.target.value })} /> +
    +
      +

      {this.props.language.background.customURL} this.resetItem('customBackground')}>{this.props.language.reset}

      + +
    +
      +

      {this.props.language.background.custombackground} this.resetItem('customBackground')}>{this.props.language.reset}

      + + +
    +
      +

      {this.props.language.background.customcolour} this.resetItem('customBackgroundColour')}>{this.props.language.reset}

      + + {colourSettings} +
    +
    +
    ); } } \ No newline at end of file diff --git a/src/components/modals/settings/sections/LanguageSettings.jsx b/src/components/modals/settings/sections/LanguageSettings.jsx index 58a421ff..3c058006 100644 --- a/src/components/modals/settings/sections/LanguageSettings.jsx +++ b/src/components/modals/settings/sections/LanguageSettings.jsx @@ -4,7 +4,7 @@ export default class LanguageSettings extends React.PureComponent { render() { return (
    -

    {this.props.language.language}

    +

    {this.props.language.language}

    SettingsFunctions.setSearchEngine(document.getElementById('searchEngine').value)}> - {searchEngines.map((engine) => - - )} - - - -
      -

      {this.props.language.searchbar.custom} this.resetSearch()}>{this.props.language.reset}

      - -
    -
    + +
    +
      + + +
    +
      +

      {this.props.language.searchbar.custom} this.resetSearch()}>{this.props.language.reset}

      + +
    +
    +
    ); } } \ No newline at end of file diff --git a/src/components/modals/Addons.jsx b/src/components/modals/tabs/Addons.jsx similarity index 80% rename from src/components/modals/Addons.jsx rename to src/components/modals/tabs/Addons.jsx index ced5a8f9..f4272781 100644 --- a/src/components/modals/Addons.jsx +++ b/src/components/modals/tabs/Addons.jsx @@ -1,8 +1,8 @@ import React from 'react'; import LocalMallIcon from '@material-ui/icons/LocalMall'; import { toast } from 'react-toastify'; -import Item from './marketplace/Item'; -import MarketplaceFunctions from '../../modules/marketplaceFunctions'; +import Item from '../marketplace/Item'; +import MarketplaceFunctions from '../../../modules/marketplaceFunctions'; export default class Addons extends React.PureComponent { constructor(...args) { @@ -136,16 +136,9 @@ export default class Addons extends React.PureComponent { }; }; - document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); - document.getElementById('center').classList.toggle('backgroundEffects'); this.setState({ installed: JSON.parse(localStorage.getItem('installed')) }); } - componentWillUnmount() { - document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); - document.getElementById('center').classList.toggle('backgroundEffects'); - } - render() { let content =
    {this.state.installed.map((item) => @@ -169,21 +162,16 @@ export default class Addons extends React.PureComponent {
    ; } - return
    - × -

    {this.props.modalLanguage.title}

    -
    - - - -
    -
    - - -

    {this.props.language.added}

    - {content} -
    - this.toggle()} language={this.props.marketplaceLanguage.product} /> -
    ; + return ( +
    +
    + + +

    {this.props.language.added}

    + {content} +
    + this.toggle()} language={this.props.marketplaceLanguage.product} /> +
    + ); } } diff --git a/src/components/modals/Marketplace.jsx b/src/components/modals/tabs/Marketplace.jsx similarity index 74% rename from src/components/modals/Marketplace.jsx rename to src/components/modals/tabs/Marketplace.jsx index f773da52..055e658d 100644 --- a/src/components/modals/Marketplace.jsx +++ b/src/components/modals/tabs/Marketplace.jsx @@ -2,10 +2,10 @@ import React from 'react'; import WifiOffIcon from '@material-ui/icons/WifiOff'; import ArrowBackIcon from '@material-ui/icons/ArrowBack'; import { toast } from 'react-toastify'; -import Item from './marketplace/Item'; -import MarketplaceFunctions from '../../modules/marketplaceFunctions'; -import * as Constants from '../../modules/constants'; -import Items from './marketplace/Items'; +import Item from '../marketplace/Item'; +import MarketplaceFunctions from '../../../modules/marketplaceFunctions'; +import * as Constants from '../../../modules/constants'; +import Items from '../marketplace/Items'; export default class Marketplace extends React.PureComponent { constructor(...args) { @@ -35,22 +35,12 @@ export default class Marketplace extends React.PureComponent { } } - this.offlineHTML =
    - × -

    {this.props.modalLanguage.title}

    -
    - - - -
    -
    + this.offlineHTML =

    {this.props.language.offline.title}

    {this.props.language.offline.description}

    -
    ; } @@ -161,51 +151,29 @@ export default class Marketplace extends React.PureComponent { } componentDidMount() { - document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); - document.getElementById('center').classList.toggle('backgroundEffects'); if (navigator.onLine === false) return; this.getItems(); } - componentWillUnmount() { - document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); - document.getElementById('center').classList.toggle('backgroundEffects'); - } - render() { if (navigator.onLine === false) return this.offlineHTML; if (this.state.done === false) { - return
    - × -

    {this.props.modalLanguage.title}

    -
    - - - -
    -
    + return ( +
    -

    Loading...

    +

    {this.props.updateLanguage.loading}

    -
    -
    ; +
    + ) } - return
    - × -

    {this.props.modalLanguage.title}

    -
    - - - -
    -
    + return ( +
    +
    -

    {this.state.featured.title}

    -

    {this.state.featured.name}

    - +

    {this.state.featured.title}

    +

    {this.state.featured.name}

    +
    this.toggle('item', 'quote_packs', input)} seeMoreFunction={() => this.toggle('seemore', 'quote_packs')} /> - this.toggle('item', 'theme', input)} - seeMoreFunction={() => this.toggle('seemore', 'themes')} /> + seeMoreFunction={() => this.toggle('seemore', 'themes')} /> */ }
    -
    ; +
    + ) } } \ No newline at end of file diff --git a/src/components/modals/Settings.jsx b/src/components/modals/tabs/Settings.jsx similarity index 54% rename from src/components/modals/Settings.jsx rename to src/components/modals/tabs/Settings.jsx index f5656217..67656edb 100644 --- a/src/components/modals/Settings.jsx +++ b/src/components/modals/tabs/Settings.jsx @@ -1,13 +1,12 @@ import React from 'react'; -import SettingsFunctions from '../../modules/settingsFunctions'; -import Checkbox from './settings/Checkbox'; -import Slider from './settings/Slider'; -import Section from './settings/Section'; +import SettingsFunctions from '../../../modules/settingsFunctions'; +import Checkbox from '../settings/Checkbox'; +import Section from '../settings/Section'; import { toast } from 'react-toastify'; -import BackgroundSettings from './settings/sections/BackgroundSettings'; -import SearchSettings from './settings/sections/SearchSettings'; -import LanguageSettings from './settings/sections/LanguageSettings'; +import BackgroundSettings from '../settings/sections/BackgroundSettings'; +import SearchSettings from '../settings/sections/SearchSettings'; +import LanguageSettings from '../settings/sections/LanguageSettings'; export default class Settings extends React.PureComponent { resetGreeting() { @@ -15,20 +14,17 @@ export default class Settings extends React.PureComponent { toast(this.props.toastLanguage.reset); } - updateCurrent() { + componentDidMount() { + // Settings document.getElementById('greetingName').value = localStorage.getItem('greetingName'); document.getElementById('language').value = localStorage.getItem('language'); - if (localStorage.getItem('darkTheme') === 'true') { + if (document.getElementById('modal').classList.contains('dark')) { // Dark theme support for dropdowns const choices = document.getElementsByClassName('choices'); for (let i = 0; i < choices.length; i++) choices[i].style.backgroundColor = '#2f3542'; } - } - componentDidMount() { - this.updateCurrent(); - - document.getElementById('file-input').onchange = (e) => { + document.getElementById('file-input').onchange = (e) => { // import settings const file = e.target.files[0]; if (file.type !== 'application/json') return console.error(`expected json, got ${file.type}`); @@ -41,28 +37,10 @@ export default class Settings extends React.PureComponent { toast(this.props.toastLanguage.imported); }; }; - - document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); - document.getElementById('center').classList.toggle('backgroundEffects'); - } - - componentWillUnmount() { - document.getElementById('backgroundImage').classList.toggle('backgroundEffects'); - document.getElementById('center').classList.toggle('backgroundEffects'); } render() { return ( -
    - × -

    {this.props.modalLanguage.title}

    -
    - - - -
    -
    -
    @@ -71,6 +49,7 @@ export default class Settings extends React.PureComponent {
    +
    @@ -79,40 +58,35 @@ export default class Settings extends React.PureComponent {
    +
    +
    -
    - -
    -
    - -
    -
    -

    {this.props.language.offline}

    - -
    -
    -

    {this.props.language.experimental.dark}

    - -
    + + + + + +
    +
    +
    - - - + +
    + - - + +
    -
    ); } } diff --git a/src/components/widgets/Background.jsx b/src/components/widgets/Background.jsx index e1037d9c..48841117 100644 --- a/src/components/widgets/Background.jsx +++ b/src/components/widgets/Background.jsx @@ -25,12 +25,13 @@ export default class Background extends React.PureComponent { localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings)); } } - const background = typeof gradientSettings === 'object' && gradientSettings !== null ? this.gradientStyleBuilder(gradientSettings) : `background-image: url(${url});`; + const background = typeof gradientSettings === 'object' && gradientSettings !== null ? this.gradientStyleBuilder(gradientSettings) : `background-image: url(${url})`; + let brightness = localStorage.getItem('brightness'); + if (localStorage.getItem('brightnessTime') && new Date().getHours() > 18) brightness = 75; document.querySelector('#backgroundImage').setAttribute( 'style', - `${background}; - -webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${localStorage.getItem('brightness')}%);` + `${background}; -webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${brightness}%);` ); if (credit === 'false') document.querySelector('#credits').style.display = 'none'; // Hide the credit @@ -40,6 +41,7 @@ export default class Background extends React.PureComponent { let credit = photographer; if (unsplash) credit = `${photographer} on Unsplash`; document.querySelector('#photographer').insertAdjacentHTML("beforeend", ` ${credit}`); // Append credit + document.getElementById('credit').textContent = credit; } doOffline() { // Handles setting the background if the user is offline @@ -49,7 +51,7 @@ export default class Background extends React.PureComponent { const randomImage = offlineImages[photographer].photo[ Math.floor(Math.random() * offlineImages[photographer].photo.length) ]; // Select a random image - const url = `../offline-images/${randomImage}.jpeg`; + const url = `../offline-images/${randomImage}.jpg`; this.setBackground(url); this.setCredit(photographer); diff --git a/src/components/widgets/Clock.jsx b/src/components/widgets/Clock.jsx index b1f17764..6ba3d149 100644 --- a/src/components/widgets/Clock.jsx +++ b/src/components/widgets/Clock.jsx @@ -65,8 +65,11 @@ export default class Clock extends React.PureComponent { } render() { + if (localStorage.getItem('time') === 'false') return null; + let clockHTML =

    {this.state.time}{this.state.ampm}

    ; if (localStorage.getItem('analog') === 'true') clockHTML = ; + return clockHTML; } } diff --git a/src/components/widgets/Favourite.jsx b/src/components/widgets/Favourite.jsx index f53613f8..c0473305 100644 --- a/src/components/widgets/Favourite.jsx +++ b/src/components/widgets/Favourite.jsx @@ -28,7 +28,7 @@ export default class Favourite extends React.PureComponent { } render() { - if (localStorage.getItem('favouriteEnabled') === 'false') return null; + if (localStorage.getItem('favouriteEnabled') === 'false' || localStorage.getItem('background') === 'false' || localStorage.getItem('customBackgroundColour') || localStorage.getItem('customBackground')) return null; return
    {this.state.favourited}
    diff --git a/src/components/widgets/Greeting.jsx b/src/components/widgets/Greeting.jsx index 21729bf9..3f986632 100644 --- a/src/components/widgets/Greeting.jsx +++ b/src/components/widgets/Greeting.jsx @@ -6,7 +6,7 @@ export default class Greeting extends React.PureComponent { this.state = { greeting: '' }; - } + } doEvents(time, message) { if (localStorage.getItem('events') === 'false') return message; @@ -15,9 +15,9 @@ export default class Greeting extends React.PureComponent { const m = time.getMonth(); const d = time.getDate(); - if (m === 11 && d === 25) message = 'Merry Christmas'; // If it's December 25th, set the greeting string to "Merry Christmas" - else if (m === 0 && d === 1) message = 'Happy new year'; // If the date is January 1st, set the greeting string to "Happy new year" - else if (m === 9 && d === 31) message = 'Happy Halloween'; // If it's October 31st, set the greeting string to "Happy Halloween" + if (m === 11 && d === 25) message = this.props.language.christmas; // If it's December 25th, set the greeting string to "Merry Christmas" + else if (m === 0 && d === 1) message = this.props.language.newyear; // If the date is January 1st, set the greeting string to "Happy new year" + else if (m === 9 && d === 31) message = this.props.language.halloween; // If it's October 31st, set the greeting string to "Happy Halloween" return message; } diff --git a/src/components/widgets/Maximise.jsx b/src/components/widgets/Maximise.jsx index f940f526..fff9abaf 100644 --- a/src/components/widgets/Maximise.jsx +++ b/src/components/widgets/Maximise.jsx @@ -12,9 +12,7 @@ export default class View extends React.PureComponent { setAttribute(blur, brightness) { document.querySelector('#backgroundImage').setAttribute( 'style', - `background-image: url(${document.getElementById('backgroundImage').style.backgroundImage.replace('url("', '').replace('")', '')}); - -webkit-filter: blur(${blur}); - -webkit-filter: brightness(${brightness}%);` + `background-image: url(${document.getElementById('backgroundImage').style.backgroundImage.replace('url("', '').replace('")', '')}); -webkit-filter: blur(${blur}); -webkit-filter: brightness(${brightness}%);` ); } @@ -27,6 +25,7 @@ export default class View extends React.PureComponent { return; } }); + if (this.state.hidden === false) { this.setState({ hidden: true }); this.setAttribute(0, 100); @@ -37,7 +36,7 @@ export default class View extends React.PureComponent { } render() { - if (localStorage.getItem('view') === 'false') return null; + if (localStorage.getItem('view') === 'false' || localStorage.getItem('background') === 'false') return null; return
    this.viewStuff()} />
    diff --git a/src/components/widgets/Quote.jsx b/src/components/widgets/Quote.jsx index f8438508..1cbfedc4 100644 --- a/src/components/widgets/Quote.jsx +++ b/src/components/widgets/Quote.jsx @@ -4,13 +4,16 @@ import FileCopy from '@material-ui/icons/FilterNone'; import { toast } from 'react-toastify'; import * as Constants from '../../modules/constants'; import TwitterIcon from '@material-ui/icons/Twitter'; +import StarIcon from '@material-ui/icons/Star'; +import StarIcon2 from '@material-ui/icons/StarBorder'; export default class Quote extends React.PureComponent { constructor(...args) { super(...args); this.state = { quote: '', - author: '' + author: '', + favourited: this.favourite()} /> }; } @@ -51,6 +54,12 @@ export default class Quote extends React.PureComponent { } } + const favouriteQuote = localStorage.getItem('favouriteQuote'); + if (favouriteQuote) return this.setState({ + quote: favouriteQuote.split(' - ')[0], + author: favouriteQuote.split(' - ')[1] + }); + if (localStorage.getItem('offlineMode') === 'true') return this.doOffline(); try { // First we try and get a quote from the API... @@ -70,20 +79,36 @@ export default class Quote extends React.PureComponent { toast(this.props.language.quote); } + favourite() { + if (localStorage.getItem('favouriteQuote')) { + localStorage.removeItem('favouriteQuote'); + this.setState({ favourited: this.favourite()} /> }); + } else { + localStorage.setItem('favouriteQuote', this.state.quote + ' - ' + this.state.author); + this.setState({ favourited: this.favourite()} /> }); + } + } + componentDidMount() { if (localStorage.getItem('quote') === 'false') return; + if (localStorage.getItem('favouriteQuote')) this.setState({ favourited: this.favourite()} /> }); + if (localStorage.getItem('favouriteQuoteEnabled') === 'false') this.setState({ favourited: null }); this.getQuote(); } render() { - const copy = (localStorage.getItem('copyButton') === 'false') ? null : this.copyQuote()}>; - const tweet = (localStorage.getItem('tweetButton') === 'false') ? null : - window.open(`https://twitter.com/intent/tweet?text=${this.state.quote} - ${this.state.author} on @getmue`, '_blank').focus()}/>; + if (localStorage.getItem('quote') === 'false') return null; + + let copy = this.copyQuote()}>; + if (localStorage.getItem('copyButton') === 'false') copy = null; + + let tweet = window.open(`https://twitter.com/intent/tweet?text=${this.state.quote} - ${this.state.author} on @getmue`, '_blank').focus()}/> + if (localStorage.getItem('tweetButton') === 'false') tweet = null; return (

    {`${this.state.quote}`}

    -

    {this.state.author} {copy} {tweet}

    +

    {this.state.author} {copy} {tweet} {this.state.favourited}

    ); } diff --git a/src/components/widgets/Search.jsx b/src/components/widgets/Search.jsx index 9f143a9c..c4a3612e 100644 --- a/src/components/widgets/Search.jsx +++ b/src/components/widgets/Search.jsx @@ -1,8 +1,26 @@ import React from 'react'; import SearchIcon from '@material-ui/icons/Search'; +import MicIcon from '@material-ui/icons/Mic'; + const searchEngines = require('../../modules/searchEngines.json'); export default class Search extends React.PureComponent { + constructor(...args) { + super(...args); + this.state = { + url: '', + query: '' + }; + } + + startSpeechRecognition() { + if (localStorage.getItem('voiceSearch') === 'false') return; + const voiceSearch = new window.webkitSpeechRecognition(); + voiceSearch.start(); + voiceSearch.onresult = (event) => document.getElementById('searchtext').value = event.results[0][0].transcript; + voiceSearch.onend = () => setTimeout(() => window.location.href = this.state.url + `?${this.state.query}=` + document.getElementById('searchtext').value, 1000); + } + render() { if (localStorage.getItem('searchBar') === 'false') return null; @@ -24,14 +42,24 @@ export default class Search extends React.PureComponent { window.location.href = url + `?${query}=` + value; }; + let microphone = null; + if (localStorage.getItem('voiceSearch') === 'true') { + this.setState({ + url: url, + query: query + }); + microphone = this.startSpeechRecognition()}/>; + } + return (