diff --git a/.gitignore b/.gitignore index d31b7bd3..88927bbd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ build/ # Files package-lock.json yarn-error.log -yarn.lock +yarn.lock \ No newline at end of file diff --git a/README.md b/README.md index 7ecf87e0..44be0b19 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,8 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an * [Building](#building) * [Credits](#credits) * [Maintainers](#maintainers) - * [Contributors]() + * [Contributors](#contributors) + * [Translators](#translators) * [Other](#other) ## Screenshot @@ -42,12 +43,10 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an * Search bar * Settings - enable/disable various features and customise parts of Mue * Update modal, copy button and more! - -## Planned Features -* Multilingual support +* Marketplace - download custom photo packs, quote packs, preset settings and themes made by the community! ## Installation -*A demo of the tab can be found [here](https://mue.now.sh)* +*A demo of the tab can be found [here](https://demo.muetab.xyz)* ### Chrome [![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
@@ -67,15 +66,15 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an ### Development #### Requirements
    -
  1. Git (optional)
  2. +
  3. Git
  4. Node.JS
  5. A suitable browser
Starting
    -
  1. clone the repository using git clone https://github.com/mue/mue.git -
  2. run yarn or npm i to install all needed dependencies -
  3. run yarn start or npm start to start testing +
  4. Clone the repository using git clone https://github.com/mue/mue.git +
  5. Run yarn or npm i to install all needed dependencies +
  6. Run yarn start or npm start to start testing
  7. Code your heart out! (See the sections below for how to build the extension)

Building

@@ -123,17 +122,22 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an ## Credits ### Maintainers -[ohlookitsderpy](https://github.com/ohlookitsderpy) - Founder, Lead development, Photographer
-[TurboMarshmello](https://github.com/TurboMarshmello) - Name, Lead design, Photographer
+[David Ralph (ohlookitsderpy)](https://github.com/ohlookitsderpy) - Founder, Lead development, Photographer
+[Alex Sparkes](https://github.com/alexsparkes) - Name, Lead design, Photographer
### Contributors -[Wessel](https://github.com/Wessel) - Development
-[Isaac](https://github.com/eartharoid) - QA, Development, Photographer
+[Wessel Tip](https://github.com/Wessel) - Development
+[Isaac (Eartharoid)](https://github.com/eartharoid) - QA, Development, Photographer
+ +### Translators +English - [David Ralph (ohlookitsderpy)](https://github.com/ohlookitsderpy) & [Alex Sparkes](https://github.com/alexsparkes) +Dutch - [Wessel Tip](https://github.com/Wessel) +French - [Alex Sparkes](https://github.com/alexsparkes) +Norwegian - [Anders](https://github.com/FuryingFox) ### Other [Pexels](https://pexels.com) - Stock photos used for offline mode - -[Opera Forum](https://forums.opera.com/topic/25046/how-to-disable-completely-the-speed-dial/14) - Portions of code to add Opera support
+[Opera Forum](https://forums.opera.com/topic/25046/how-to-disable-completely-the-speed-dial/14) - Portions of code to add Opera support [Google Fonts](https://fonts.google.com/specimen/Lexend+Deca) - Lexend Deca font -And many thanks to [Highholding](https://discord.bio/p/highholding), [Noa Shapira](#), [Roee Lupo](https://github.com/MrSheldon), [Jeroen](#), [Glasvegas](https://twitter.com/_glasvegas), [Anders](https://github.com/FuryingFox/), [Oded Shapira](https://twitter.com/dondishdev) and [Nikka Lai](#) for letting us use their wonderful photographs +And many thanks to [Highholding](https://discord.bio/p/highholding), [Noa Shapira](#), [Roee Lupo](https://github.com/RoeeLupo), [Jeroen](#), [Glasvegas](https://twitter.com/_glasvegas), [Anders](https://github.com/FuryingFox), [Oded Shapira](https://twitter.com/dondishdev), Jacob Tyrrell and [Nikka Lai](#) for letting us use their wonderful photographs diff --git a/manifest/chrome.json b/manifest/chrome.json index 64213ea3..2bd7a9eb 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": "3.0.1", + "version": "4.0.0", "browser_action": { "default_icon": "./icons/extension-icon.png" }, diff --git a/manifest/firefox.json b/manifest/firefox.json index adc54e89..29679cf2 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": "3.0.1", + "version": "4.0.0", "browser_action": { "default_icon": "./icons/extension-icon.png" }, diff --git a/manifest/opera.json b/manifest/opera.json index 146ff2fc..2a72a290 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": "3.0.1", + "version": "4.0.0", "browser_action": { "default_icon": "./icons/extension-icon.png" }, diff --git a/package.json b/package.json index 6f13a392..60efd5e2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "author": "David \"ohlookitsderpy\" Ralph (https://derpyenterprises.org)", "maintainers": [ "David \"ohlookitsderpy\" Ralph (https://derpyenterprises.org)", - "Alex \"TurboMarshmello\" Sparkes (https://github.com/TurboMarshmello)" + "Alex \"TurboMarshmello\" Sparkes (https://github.com/alexsparkes)" ], "description": "Fast, open and free-to-use new tab page for most modern browsers.", "repository": { @@ -13,21 +13,22 @@ "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": "3.0.1", + "version": "4.0.0", "dependencies": { + "@eartharoid/dtf": "^1.0.7", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@muetab/quotes": "^1.0.0", - "copy-text-to-clipboard": "^2.2.0", + "detect-browser-language": "0.0.2", "react": "^16.13.1", "react-clock": "^2.4.0", "react-dom": "^16.13.1", "react-modal": "^3.11.2", - "react-scripts": "3.4.1", "react-toastify": "^6.0.8", "supports-webp": "^2.0.1" }, "devDependencies": { + "react-scripts": "3.4.1", "node-sass": "^4.14.1" }, "scripts": { diff --git a/public/icons/iconmonstr-twitter.svg b/public/icons/iconmonstr-twitter.svg new file mode 100644 index 00000000..19705754 --- /dev/null +++ b/public/icons/iconmonstr-twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/mue_verified.svg b/public/icons/mue_verified.svg new file mode 100644 index 00000000..3db434a7 --- /dev/null +++ b/public/icons/mue_verified.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/undraw_celebration.svg b/public/icons/undraw_celebration.svg new file mode 100644 index 00000000..f0fcc804 --- /dev/null +++ b/public/icons/undraw_celebration.svg @@ -0,0 +1 @@ +celebration \ No newline at end of file diff --git a/public/index.html b/public/index.html index b615b75e..099c3737 100644 --- a/public/index.html +++ b/public/index.html @@ -1,17 +1,16 @@ + + + + + + New Tab + - - - - - - New Tab - - - - -
- + + +
+ \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index d1d67eb9..595b374e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,20 +1,21 @@ import React from 'react'; -import Background from './components/Background'; -import Clock from './components/Clock'; -import Greeting from './components/Greeting'; -import Quote from './components/Quote'; -import Search from './components/Search'; -import Credit from './components/Credit'; +import Background from './components/widgets/Background'; +import Clock from './components/widgets/Clock'; +import Greeting from './components/widgets/Greeting'; +import Quote from './components/widgets/Quote'; +import Search from './components/widgets/Search'; import Navbar from './components/Navbar'; +import SettingsFunctions from './modules/settingsFunctions'; import { ToastContainer } from 'react-toastify'; import Modal from 'react-modal'; +import RoomIcon from '@material-ui/icons/Room'; -import './scss/index.scss'; -import 'react-toastify/dist/ReactToastify.css'; - -const defaultSettings = require('./modules/defaultSettings.json'); -const Settings = React.lazy(() => import('./components/Settings')); -const Update = React.lazy(() => import('./components/Update')); +// 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')); +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 = () =>
; export default class App extends React.PureComponent { @@ -23,26 +24,17 @@ export default class App extends React.PureComponent { this.state = { settingsModal: false, - updateModal: false + updateModal: false, + marketplaceModal: false, + addonsModal: false, + quickAccessmodal: false, + welcomeModal: false }; } - setDefaultSettings() { - localStorage.clear(); - defaultSettings.forEach(element => localStorage.setItem(element.name, element.value)); - - // Set theme depending on user preferred - // if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true); - //else localStorage.setItem('darkTheme', false); - - // Finally we set this to true so it doesn't run the function on every load - localStorage.setItem('firstRun', true); - window.location.reload(); - } - // Render all the components render() { - if (!localStorage.getItem('firstRun')) this.setDefaultSettings(); + if (!localStorage.getItem('firstRun')) SettingsFunctions.setDefaultSettings(); let modalClassList = 'Modal'; if (localStorage.getItem('darkTheme') === 'true') modalClassList = 'Modal dark'; @@ -52,26 +44,75 @@ export default class App extends React.PureComponent { let language = require(`./translations/${localStorage.getItem('language')}.json`); + const theme = localStorage.getItem('theme'); + if (theme) { + let style = document.createElement('link'); + style.href = theme; + style.rel = 'stylesheet'; + document.head.appendChild(style); + } + return ( -
- - this.setState({ settingsModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} /> - - - - - - this.setState({ settingsModal: false })} isOpen={this.state.settingsModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> - this.setState({ settingsModal: false })} setDefaultSettings={() => this.setDefaultSettings()} /> - - this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> - this.setState({ updateModal: false })} /> - - + + this.setState({ settingsModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} /> + + + +
+

{language.credit}

+
+ + +
+
+ + 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({ 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/Credit.jsx b/src/components/Credit.jsx deleted file mode 100644 index b6c7bae2..00000000 --- a/src/components/Credit.jsx +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable jsx-a11y/heading-has-content */ -import RoomIcon from '@material-ui/icons/Room'; -import React from 'react'; - -export default class Credit extends React.PureComponent { - render() { - return ( -
- {/*

*/} -

{this.props.language}

-
- - -
-
- ); - } -} \ No newline at end of file diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 3a72b330..0e1f3a80 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,14 +1,18 @@ +import React from 'react'; import RefreshIcon from '@material-ui/icons/Refresh'; import Gear from '@material-ui/icons/Settings'; import NewReleases from '@material-ui/icons/NewReleases'; -import React from 'react'; export default class Navbar extends React.PureComponent { render() { - let refreshHTML =
window.location.reload()} />
+ let refreshHTML =
window.location.reload()} />
const refresh = localStorage.getItem('refresh'); if (refresh === 'false') refreshHTML = ''; + const viewedUpdate = localStorage.getItem('viewedUpdate'); + let update = ; + if (viewedUpdate === 'false') update = + return (
@@ -16,7 +20,7 @@ export default class Navbar extends React.PureComponent {
{refreshHTML}
- + {update}
); diff --git a/src/components/Search.jsx b/src/components/Search.jsx deleted file mode 100644 index 597c1d25..00000000 --- a/src/components/Search.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; - -export default class Search extends React.PureComponent { - render() { - if (localStorage.getItem('searchBar') === 'false') return
; - - let url; - - switch (localStorage.getItem('searchEngine')) { - case 'duckduckgo': url = 'https://duckduckgo.com'; break; - case 'google': url = 'https://google.com/search'; break; - case 'bing': url = 'https://bing.com/search'; break; - default: url = 'https://duckduckgo.com'; break; - } - - return