Compare commits

...

282 Commits
5.0.1 ... 6.0.0

Author SHA1 Message Date
David Ralph
42f89b3fc3 chore: release 6.0, fix firefox bug 2021-11-17 22:10:07 +00:00
David Ralph
da6c1bba63 chore: comment out unfinished things 2021-11-17 21:50:34 +00:00
dependabot[bot]
f96399c9df chore(deps): bump @mui/icons-material from 5.1.0 to 5.1.1 (#207)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.1.1/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-17 10:03:20 +00:00
dependabot[bot]
d17948f744 chore(deps): bump @mui/material from 5.1.0 to 5.1.1 (#208)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.1.1/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-17 09:08:31 +00:00
David Ralph
cf39845892 fix(translations): add missing translations 2021-11-14 16:01:45 +00:00
David Ralph
a3fb4a6522 fix: update experimental tab 2021-11-14 14:44:16 +00:00
David Ralph
f4e88cef2e fix: widget order 2021-11-12 20:20:34 +00:00
David Ralph
e786ad654c fix: background filters, addons ui, photoinformation 2021-11-12 18:34:03 +00:00
David Ralph
a356c8fe61 fix: favourite button, greeting, lightbox etc (thanks @eartharoid) 2021-11-11 22:38:10 +00:00
David Ralph
c627599590 fix: various widget fixes and cleanup etc
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-11-11 20:43:33 +00:00
4a6f93e701 refractor(widgets): Change one-lined if statements 2021-11-11 15:26:25 +01:00
David Ralph
8aca9ae31c fix: settings fix, keybinds fix (WIP), modal ui fix 2021-11-11 10:51:45 +00:00
dependabot[bot]
8966336b93 chore(deps): bump react-modal from 3.14.3 to 3.14.4 (#206)
Bumps [react-modal](https://github.com/reactjs/react-modal) from 3.14.3 to 3.14.4.
- [Release notes](https://github.com/reactjs/react-modal/releases)
- [Changelog](https://github.com/reactjs/react-modal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reactjs/react-modal/compare/v3.14.3...v3.14.4)

---
updated-dependencies:
- dependency-name: react-modal
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-11 09:13:20 +00:00
David Ralph
41750ff0e8 fix: modal ui fixes, search and quote widget fix 2021-11-10 16:20:40 +00:00
dependabot[bot]
62066fef05 chore(deps): bump @mui/icons-material from 5.0.5 to 5.1.0 (#204)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.0.5 to 5.1.0.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.1.0/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-10 15:29:25 +00:00
dependabot[bot]
eb0ffc3cc2 chore(deps): bump @mui/material from 5.0.6 to 5.1.0 (#205)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.6 to 5.1.0.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.1.0/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-10 15:06:53 +00:00
David Ralph
3bc1409f4f fix: custom video backgrounds 2021-11-06 11:00:25 +00:00
David Ralph
c15f9d20f8 Merge branch 'main' of https://github.com/mue/mue 2021-11-04 13:58:56 +00:00
David Ralph
7f5b826683 fix: various modal things, improve ui, add missing translations etc 2021-11-04 13:58:53 +00:00
dependabot[bot]
cb2c5e3117 chore(deps): bump react-toastify from 8.0.3 to 8.1.0 (#203)
Bumps [react-toastify](https://github.com/fkhadra/react-toastify) from 8.0.3 to 8.1.0.
- [Release notes](https://github.com/fkhadra/react-toastify/releases)
- [Commits](https://github.com/fkhadra/react-toastify/compare/v8.0.3...v8.1.0)

---
updated-dependencies:
- dependency-name: react-toastify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-04 11:45:24 +00:00
David Ralph
2824e7c995 feat: improve custom settings ui 2021-11-02 22:53:17 +00:00
dependabot[bot]
8888cb2144 chore(deps): bump @mui/icons-material from 5.0.4 to 5.0.5 (#200)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.0.4 to 5.0.5.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.5/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:28:30 +00:00
dependabot[bot]
1c80d37bda chore(deps): bump @mui/material from 5.0.4 to 5.0.6 (#202)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.4 to 5.0.6.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.6/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 13:25:21 +00:00
David Ralph
1b4b37d4b1 feat: improved settings and marketplace ui, better custom background support, fix webpack
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-11-01 13:24:09 +00:00
dependabot[bot]
8820343628 chore(deps): bump @mui/icons-material from 5.0.3 to 5.0.4 (#197)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.0.3 to 5.0.4.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.4/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-15 09:21:55 +01:00
dependabot[bot]
00f30c306e chore(deps): bump @mui/material from 5.0.3 to 5.0.4 (#198)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.3 to 5.0.4.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.4/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-15 09:13:44 +01:00
David Ralph
ed964c1354 feat: add preview mue button to welcome modal 2021-10-13 20:00:40 +01:00
David Ralph
bc8ef0d9f2 feat: new sliders, dropdowns, text inputs, update settings ui, fix language bug
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-10-12 22:18:47 +01:00
dependabot[bot]
14121fb975 chore(deps): bump @mui/material from 5.0.2 to 5.0.3 (#194)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.2 to 5.0.3.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.3/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-11 18:47:13 +01:00
dependabot[bot]
bd8d9fb8e4 chore(deps): bump @mui/icons-material from 5.0.1 to 5.0.3 (#195)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.0.1 to 5.0.3.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.3/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-11 18:46:14 +01:00
dependabot[bot]
2a6505799b chore(deps-dev): bump eslint from 7.32.0 to 8.0.0 (#196)
Bumps [eslint](https://github.com/eslint/eslint) from 7.32.0 to 8.0.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.32.0...v8.0.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-11 18:46:02 +01:00
David Ralph
33ef113f6d feat: add show navbar on hover setting back 2021-09-30 19:35:02 +01:00
David Ralph
a5dc2c98a0 fix: various settings tabs 2021-09-30 17:48:38 +01:00
David Ralph
c9854d5362 fix: settings tab bugs 2021-09-30 17:40:36 +01:00
dependabot[bot]
9a6119e861 chore(deps): bump @mui/material from 5.0.1 to 5.0.2 (#193)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.2/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-30 09:11:40 +01:00
David Ralph
9ac410d989 fix: background 2021-09-29 19:19:03 +01:00
David Ralph
80a7b6a56c refactor: cleanup 2021-09-28 23:04:04 +01:00
David Ralph
883f025fbb feat(translations): placeholder support, fix weather text 2021-09-27 18:37:16 +01:00
David Ralph
d1b23dc07b Merge branch 'main' of https://github.com/mue/mue 2021-09-27 17:58:34 +01:00
David Ralph
364fb4b0d7 perf: reduce custom background lag on large images, improve h3 style 2021-09-27 17:58:28 +01:00
dependabot[bot]
cef4026b97 chore(deps-dev): bump @eartharoid/deep-merge from 0.0.1 to 0.0.2 (#191)
Bumps [@eartharoid/deep-merge](https://github.com/eartharoid/deep-merge) from 0.0.1 to 0.0.2.
- [Release notes](https://github.com/eartharoid/deep-merge/releases)
- [Commits](https://github.com/eartharoid/deep-merge/compare/v0.0.1...v0.0.2)

---
updated-dependencies:
- dependency-name: "@eartharoid/deep-merge"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 10:17:44 +01:00
dependabot[bot]
5702c45187 chore(deps): bump react-toastify from 8.0.2 to 8.0.3 (#190)
Bumps [react-toastify](https://github.com/fkhadra/react-toastify) from 8.0.2 to 8.0.3.
- [Release notes](https://github.com/fkhadra/react-toastify/releases)
- [Commits](https://github.com/fkhadra/react-toastify/compare/v8.0.2...v8.0.3)

---
updated-dependencies:
- dependency-name: react-toastify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 10:17:34 +01:00
David Ralph
e7dc9f04d1 feat: new settings tab header, update keybinds and widget order ui
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-09-26 18:03:32 +01:00
David Ralph
bc9f68e0c1 fix: first load not working 2021-09-23 15:56:41 +01:00
dependabot[bot]
d2d7083d3d chore(deps): bump @mui/icons-material from 5.0.0 to 5.0.1 (#188)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.1/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-23 09:23:09 +01:00
dependabot[bot]
43ad2c31f8 chore(deps): bump @mui/material from 5.0.0 to 5.0.1 (#189)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.1/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-23 09:14:58 +01:00
David Ralph
fa485c35c3 Merge branch 'main' of https://github.com/mue/mue 2021-09-20 21:23:42 +01:00
David Ralph
231966546f feat: improve settings tabs and sidebar 2021-09-20 21:23:34 +01:00
BigTear
95c6216b0c feat(translations): Update Chinese translation (#187)
Add new items translation and fix some localized words
2021-09-20 10:16:03 +01:00
David Ralph
52745a267f feat: background interval for custom 2021-09-19 20:10:22 +01:00
David Ralph
cbbc911cc3 feat: create tab local quote pack/photo pack import (WIP) 2021-09-19 19:50:55 +01:00
David Ralph
e78611cb05 chore: username change 2021-09-19 16:11:19 +01:00
David Ralph
2049359a96 feat(translations): lazy load 2021-09-19 11:42:37 +01:00
David Ralph
96f26042d2 fix: toast duration setting, create quote pack section 2021-09-19 11:22:53 +01:00
David Ralph
f7ba4c0ed9 fix: reset button 2021-09-18 21:03:44 +01:00
David Ralph
4ad9d4810e feat: add create quote pack (WIP) 2021-09-18 20:51:00 +01:00
David Ralph
94e9c5d65e feat: random colour/gradient background, fix toasts 2021-09-17 19:40:22 +01:00
David Ralph
e3edc3d89e fix: quote widget zoom, add missing translations 2021-09-17 14:38:13 +01:00
David Ralph
8b4d1d18f1 feat: multiple custom quotes, fix background settings 2021-09-17 14:36:47 +01:00
David Ralph
0fd50e949c refactor(translations): cleanup and fix import settings text 2021-09-17 14:13:31 +01:00
dependabot[bot]
42b4aa1d62 chore(deps): bump @mui/icons-material from 5.0.0-rc.0 to 5.0.0 (#185)
Bumps [@mui/icons-material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-icons-material) from 5.0.0-rc.0 to 5.0.0.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-17 13:41:14 +01:00
dependabot[bot]
39fbd9336f chore(deps): bump @mui/material from 5.0.0-rc.0 to 5.0.0 (#186)
Bumps [@mui/material](https://github.com/mui-org/material-ui/tree/HEAD/packages/mui-material) from 5.0.0-rc.0 to 5.0.0.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-17 13:40:18 +01:00
David Ralph
93ba1cd9bf feat: random messages 2021-09-17 13:39:55 +01:00
David Ralph
a946d07c9c fix(translations): no longer crashes on welcome or file upload 2021-09-16 12:47:53 +01:00
David Ralph
3f3ee2dd82 fix: no animations setting not working on some things 2021-09-15 23:27:26 +01:00
David Ralph
4953298b9f fix(translations): add missing translated text 2021-09-15 22:39:29 +01:00
David Ralph
f931abf3fb feat: quick links custom icon and text only options, message widget, fix error 2021-09-15 22:38:24 +01:00
David Ralph
b97b925978 fix: translation and colour picker bugs 2021-09-14 20:15:15 +01:00
David Ralph
1c65447c55 fix: optimise background settings, add missing translation 2021-09-11 13:33:26 +01:00
David Ralph
66a3629b51 fix: photo information undefined text 2021-09-10 19:33:56 +01:00
David Ralph
7e3fc8085e refactor: cleanup background and keybinds, add translation for add custom background 2021-09-10 19:25:09 +01:00
David Ralph
6cd934acdc chore: switch from material-ui to mui 2021-09-10 19:00:45 +01:00
David Ralph
a7e7743028 feat: better remove background button
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-09-10 18:52:51 +01:00
dependabot[bot]
27668172ec chore(deps): bump react-hot-keys from 2.7.0 to 2.7.1 (#184)
Bumps [react-hot-keys](https://github.com/jaywcjlove/react-hotkeys) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/jaywcjlove/react-hotkeys/releases)
- [Commits](https://github.com/jaywcjlove/react-hotkeys/compare/v2.7.0...v2.7.1)

---
updated-dependencies:
- dependency-name: react-hot-keys
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-10 17:08:06 +01:00
David Ralph
b0eeff1bf8 feat(translations): new translation system 2021-09-10 16:38:53 +01:00
David Ralph
941c168486 fix: about tab images 2021-09-09 15:18:59 +01:00
xXFreeFunXx
aceba529ba Update german translation (#183)
The Github link on the setup page needs to be adjusted.
More details in the Discord.
2021-09-09 14:48:20 +01:00
David Ralph
2d7db1558d fix: custom background settings 2021-09-08 21:30:03 +01:00
David Ralph
102078744e feat: multiple custom backgrounds (WIP) 2021-09-08 20:58:07 +01:00
David Ralph
6bb461b8a2 fix: use constants, improve photoinformation ui 2021-09-08 11:05:34 +01:00
David Ralph
2984e162cc feat: check for addon updates, add attribution to photo location map 2021-09-07 20:42:56 +01:00
David Ralph
b86e73f2fc feat: clicking on location map now opens in openstreetmap 2021-09-07 19:10:04 +01:00
David Ralph
22ef3ad139 feat: allow duckduckgo proxy on map 2021-09-06 19:55:04 +01:00
David Ralph
26ae76accc feat: map for background location
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-09-06 19:35:31 +01:00
dependabot[bot]
da2c70f897 chore(deps): bump react-hot-keys from 2.6.2 to 2.7.0 (#182)
Bumps [react-hot-keys](https://github.com/jaywcjlove/react-hotkeys) from 2.6.2 to 2.7.0.
- [Release notes](https://github.com/jaywcjlove/react-hotkeys/releases)
- [Commits](https://github.com/jaywcjlove/react-hotkeys/compare/v2.6.2...v2.7.0)

---
updated-dependencies:
- dependency-name: react-hot-keys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-06 09:29:06 +01:00
David Ralph
c63a13a4c2 feat: update addons, sideload error modal, show reminder for preset settings 2021-09-05 20:52:26 +01:00
David Ralph
5baf067ff1 refactor: css cleanup 2021-09-05 14:19:19 +01:00
David Ralph
7f71321e67 feat: better keybinds ui, fix notes, improve search dropdown etc 2021-09-04 12:20:58 +01:00
David Ralph
3cc8031c84 fix: search dropdown selected hover effects 2021-09-03 12:34:34 +01:00
David Ralph
b5c3ca201e fix: demo 2021-09-03 12:31:12 +01:00
David Ralph
604834c4d7 fix: notes position, navbar hot reload 2021-09-02 15:27:00 +01:00
David Ralph
d368270553 Merge branch 'main' of https://github.com/mue/mue 2021-09-02 13:55:51 +01:00
David Ralph
8cbe3b909b fix: responsive welcome modal on smaller resolutions 2021-09-02 13:55:42 +01:00
dependabot[bot]
b0399b6314 chore(deps): bump react-toastify from 8.0.0 to 8.0.2 (#181)
Bumps [react-toastify](https://github.com/fkhadra/react-toastify) from 8.0.0 to 8.0.2.
- [Release notes](https://github.com/fkhadra/react-toastify/releases)
- [Commits](https://github.com/fkhadra/react-toastify/compare/v8.0.0...v8.0.2)

---
updated-dependencies:
- dependency-name: react-toastify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-01 11:12:36 +01:00
David Ralph
a00037747b fix: modal navbar tab not working 2021-08-29 18:02:25 +01:00
David Ralph
5af8dfac11 style: change about and search to use recent code 2021-08-29 11:02:55 +01:00
David Ralph
21f8b63b80 fix: search dropdown select, cleanup functional components 2021-08-28 19:14:22 +01:00
David Ralph
67ab7c8674 feat: new refresh button options 2021-08-28 18:56:59 +01:00
David Ralph
6b23e56bd6 chore: update readme 2021-08-28 18:04:00 +01:00
David Ralph
8b25175b9c fix: search dropdown css 2021-08-28 16:59:09 +01:00
David Ralph
06038a201e refactor: webpack alias imports 2021-08-28 15:34:12 +01:00
David Ralph
4db47d9fec refactor: cleanup, use createRef etc 2021-08-27 23:08:32 +01:00
David Ralph
fcff3e44a6 refactor: codacy and some style changes etc 2021-08-27 19:42:40 +01:00
David Ralph
abe70617d8 fix: console error and codacy 2021-08-27 18:27:11 +01:00
dependabot[bot]
feb7e1d93c chore(deps): bump react-toastify from 7.0.4 to 8.0.0 (#179)
Bumps [react-toastify](https://github.com/fkhadra/react-toastify) from 7.0.4 to 8.0.0.
- [Release notes](https://github.com/fkhadra/react-toastify/releases)
- [Commits](https://github.com/fkhadra/react-toastify/compare/v7.0.4...v8.0.0)

---
updated-dependencies:
- dependency-name: react-toastify
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-27 18:12:40 +01:00
David Ralph
de4ffbcb0a fix: add hover effect to search dropdown, custom support etc 2021-08-26 19:48:20 +01:00
David Ralph
e5f8cf3e66 feat: add #143 2021-08-25 13:55:20 +01:00
David Ralph
10f27d24b0 feat: new keybinds, language support etc 2021-08-25 13:28:41 +01:00
David Ralph
4a4e4604e8 feat: add no animations setting back, text shadow/border option 2021-08-25 12:01:48 +01:00
David Ralph
3ed2171a34 feat: keybinds (WIP) 2021-08-25 11:25:46 +01:00
dependabot[bot]
d33a879281 chore(deps): bump @material-ui/core from 5.0.0-beta.4 to 5.0.0-beta.5 (#178)
Bumps [@material-ui/core](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui) from 5.0.0-beta.4 to 5.0.0-beta.5.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.5/packages/material-ui)

---
updated-dependencies:
- dependency-name: "@material-ui/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-25 10:29:19 +01:00
dependabot[bot]
d91b939135 chore(deps): bump @material-ui/icons from 5.0.0-beta.4 to 5.0.0-beta.5 (#177)
Bumps [@material-ui/icons](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui-icons) from 5.0.0-beta.4 to 5.0.0-beta.5.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.5/packages/material-ui-icons)

---
updated-dependencies:
- dependency-name: "@material-ui/icons"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-25 10:28:11 +01:00
David Ralph
daee291aa9 fix: welcome text, remove old buggy global widget zoom 2021-08-23 15:52:05 +01:00
David Ralph
30768053eb chore: remove umami, release 5.3.2 2021-08-23 15:33:09 +01:00
David Ralph
1d99622123 chore: release 5.3.1 2021-08-23 12:01:25 +01:00
David Ralph
66ac192c09 chore(translations): add umami warning to stats tab when turned off as well 2021-08-22 22:21:40 +01:00
David Ralph
37464acf85 chore: use constants for other welcome link 2021-08-22 22:15:13 +01:00
David Ralph
c687b2fb67 fix: improve welcome modal text, cleanup settings helpers slightly 2021-08-22 22:12:47 +01:00
David Ralph
6bf6cca8c6 chore: release 5.3 2021-08-22 16:12:13 +01:00
David Ralph
096df4f073 fix: tab name language, favourite marketplace backgrounds, birthday greeting message etc 2021-08-22 15:00:05 +01:00
David Ralph
490f42a9ad style: codacy fixes 2021-08-21 11:11:00 +01:00
David Ralph
ef2f666ccf perf: add eventbus unmount in more places and optimise stats tab 2021-08-20 22:06:40 +01:00
David Ralph
afcead634b fix: text shadow and chrome manifest 2021-08-20 19:20:59 +01:00
David Ralph
98c857e7ad fix: photoinformation console errors 2021-08-20 11:52:05 +01:00
David Ralph
34cf696bb4 fix: quicklinks zoom 2021-08-19 22:57:16 +01:00
David Ralph
2f3252d15e refactor: cleanup photoinformation slightly 2021-08-19 22:24:03 +01:00
David Ralph
7ce2afb773 refactor: cleanup background widget slightly 2021-08-19 16:32:10 +01:00
David Ralph
203ff27ee1 fix: responsive modal 2021-08-19 15:35:51 +01:00
David Ralph
50b1d16171 fix: responsive marketplace items (WIP) 2021-08-18 23:13:26 +01:00
David Ralph
13825c5525 fix: responsive sidebar on smaller resolutions 2021-08-18 15:26:03 +01:00
David Ralph
a91d5843b9 fix: clock hot reload 2021-08-18 14:48:52 +01:00
David Ralph
fb15a1037b fix: close #176 2021-08-18 11:28:01 +01:00
David Ralph
c66add33d2 fix: modal transition and about tooltips 2021-08-17 22:20:27 +01:00
David Ralph
6ec57c75d4 fix: hot reload bugs 2021-08-17 17:09:54 +01:00
David Ralph
54e7a3a33f fix: widget order ui, tab name language etc 2021-08-17 16:31:42 +01:00
David Ralph
7e2432b9b4 feat: navbar zoom 2021-08-16 14:36:34 +01:00
David Ralph
640b83e1c3 fix: search on enter 2021-08-16 14:06:57 +01:00
David Ralph
4d3c7cbbe6 fix: favourite button, optimise widgets and remove dependency 2021-08-16 12:21:37 +01:00
dependabot[bot]
23251d248b chore(deps): bump @material-ui/icons from 5.0.0-beta.1 to 5.0.0-beta.4 (#175)
Bumps [@material-ui/icons](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui-icons) from 5.0.0-beta.1 to 5.0.0-beta.4.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.4/packages/material-ui-icons)

---
updated-dependencies:
- dependency-name: "@material-ui/icons"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-16 10:42:11 +01:00
dependabot[bot]
ba31ea5841 chore(deps): bump @material-ui/core from 5.0.0-beta.3 to 5.0.0-beta.4 (#174)
Bumps [@material-ui/core](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui) from 5.0.0-beta.3 to 5.0.0-beta.4.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.4/packages/material-ui)

---
updated-dependencies:
- dependency-name: "@material-ui/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-16 10:39:23 +01:00
David Ralph
4f5233fab9 refactor: cleanup 2021-08-15 22:28:37 +01:00
David Ralph
5e4a14ba2c fix: weather typo 2021-08-15 20:33:58 +01:00
David Ralph
e82ac7da9e perf: reduce localstorage calls etc 2021-08-15 20:33:06 +01:00
David Ralph
16485c3d2c fix: tooltip css, create tab translation, other small css bugs 2021-08-15 16:08:16 +01:00
Vicente
9a8a360e21 feat(translations): updated spanish translation (#173)
* feat(translations): updated spanish translation

* fix(translations): improved some translations
2021-08-15 16:07:17 +01:00
David Ralph
cd5364dd36 style: better create tab settings ui 2021-08-15 15:12:03 +01:00
David Ralph
70273798b6 feat(translations): add WIP support for create, fix stats issue 2021-08-15 11:59:30 +01:00
David Ralph
baaa780ade feat: improved create ui, prepare for photo and quote packs etc 2021-08-15 11:28:21 +01:00
David Ralph
39751736ca refactor: imports etc 2021-08-14 20:10:48 +01:00
David Ralph
1a8bb69288 feat: create addon tab, translation support for stats tab, fixes etc 2021-08-14 17:23:54 +01:00
David Ralph
b8c793741f build: fix firefox, add 2 new things to stats tab 2021-08-14 15:03:01 +01:00
David Ralph
0f20983c37 feat: open new tab on install and add uninstall page 2021-08-14 15:01:45 +01:00
David Ralph
9c3b8c7f59 feat: stats tab (WIP) 2021-08-11 18:15:54 +01:00
David Ralph
943d817e71 perf: optimise greeting 2021-08-11 16:21:35 +01:00
Wessel Tip
564b82c427 refractor: Update gradientStyleBuilder 2021-08-11 14:06:02 +02:00
dependabot[bot]
26df915801 chore(deps): bump @material-ui/core from 5.0.0-beta.2 to 5.0.0-beta.3 (#172)
Bumps [@material-ui/core](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui) from 5.0.0-beta.2 to 5.0.0-beta.3.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.3/packages/material-ui)

---
updated-dependencies:
- dependency-name: "@material-ui/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-09 10:55:36 +01:00
David Ralph
eefc594ec1 fix: improvements to feedback modal 2021-08-05 17:25:46 +01:00
David Ralph
6cdfb9db3e chore: release 5.2 2021-08-02 13:47:06 +01:00
David Ralph
1ce6cb9419 fix: background offline interval 2021-08-01 18:20:38 +01:00
David Ralph
141da4ba36 fix: background proxy and offline mode hot reload bugs 2021-08-01 15:02:18 +01:00
David Ralph
9db7b210bc Merge branch 'main' of https://github.com/mue/mue 2021-07-29 14:18:34 +01:00
David Ralph
090ffe05f4 fix: about copyright link 2021-07-29 14:18:21 +01:00
David Ralph
66f6d0f7ed chore(translations): add messages.json files 2021-07-29 14:18:03 +01:00
dependabot[bot]
285145fdcb chore(deps): bump @material-ui/core from 5.0.0-beta.1 to 5.0.0-beta.2 (#171)
Bumps [@material-ui/core](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui) from 5.0.0-beta.1 to 5.0.0-beta.2.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.2/packages/material-ui)

---
updated-dependencies:
- dependency-name: "@material-ui/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-27 10:15:12 +01:00
David Ralph
37df7fb08c fix: revert using api to get temperature format 2021-07-23 10:55:20 +01:00
David Ralph
5a91fa24e9 chore: update api urls 2021-07-22 21:47:08 +01:00
David Ralph
bdd277d876 feat(translations): add support for description and chrome store page 2021-07-19 20:28:40 +01:00
David Ralph
d7be6e351d fix: firefox changelog date, cleanup background a bit 2021-07-19 10:20:00 +01:00
David Ralph
c9f2af6b96 fix: font size on builds, typo on welcome modal 2021-07-18 21:53:35 +01:00
David Ralph
b426041598 fix: marketplace background settings, reset button, intervals 2021-07-18 15:54:45 +01:00
David Ralph
2d7e138b2f fix: welcome background refresh, add more privacy tab content 2021-07-18 12:20:35 +01:00
David Ralph
332e6c33ac feat: welcome modal language hot reload 2021-07-18 10:59:38 +01:00
David Ralph
99993720f2 fix: welcome modal is now responsive, fix close button with other languages, codacy fixes etc 2021-07-18 10:43:25 +01:00
David Ralph
59a888c861 feat(translations): add support for background/quote interval 2021-07-17 19:45:05 +01:00
David Ralph
6cccad0e17 feat: change background/quote interval, use api to get temperature format 2021-07-17 19:38:00 +01:00
David Ralph
8ffd0e04cb build: fix vercel 2021-07-17 15:56:49 +01:00
David Ralph
3d6884fe9a feat: timezone setting, translation file updater 2021-07-17 15:51:57 +01:00
David Ralph
2a1e26d0c4 fix: add link, date picker, photo information, uninstall button 2021-07-17 13:43:18 +01:00
David Ralph
b842bd935e fix: discord link in about now works again 2021-07-15 17:41:51 +01:00
David Ralph
3a47089a00 fix: welcome start, marketplace item page is now responsive, update text etc 2021-07-15 17:39:38 +01:00
dependabot[bot]
e1f43dc343 chore(deps): bump @material-ui/icons from 5.0.0-beta.0 to 5.0.0-beta.1 (#168)
Bumps [@material-ui/icons](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui-icons) from 5.0.0-beta.0 to 5.0.0-beta.1.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.1/packages/material-ui-icons)

---
updated-dependencies:
- dependency-name: "@material-ui/icons"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: David Ralph <ohlookitsderpy@protonmail.com>
2021-07-15 15:09:31 +01:00
dependabot[bot]
75b3c23a38 chore(deps-dev): bump css-loader from 5.2.7 to 6.0.0 (#169)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 5.2.7 to 6.0.0.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v5.2.7...v6.0.0)

---
updated-dependencies:
- dependency-name: css-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-15 15:09:03 +01:00
dependabot[bot]
7a271190d5 chore(deps): bump @material-ui/core from 5.0.0-beta.0 to 5.0.0-beta.1 (#167)
Bumps [@material-ui/core](https://github.com/mui-org/material-ui/tree/HEAD/packages/material-ui) from 5.0.0-beta.0 to 5.0.0-beta.1.
- [Release notes](https://github.com/mui-org/material-ui/releases)
- [Changelog](https://github.com/mui-org/material-ui/blob/next/CHANGELOG.md)
- [Commits](https://github.com/mui-org/material-ui/commits/v5.0.0-beta.1/packages/material-ui)

---
updated-dependencies:
- dependency-name: "@material-ui/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-15 15:09:00 +01:00
David Ralph
c725ad4cc3 style: improve item page, update photo width/height code 2021-07-15 15:08:37 +01:00
David Ralph
c07d7ecbb0 feat: background resolution is now automatic and more accurate 2021-07-12 21:48:08 +01:00
David Ralph
99ffc82de0 refactor: update widgets and fix font change 2021-07-12 11:34:05 +01:00
David Ralph
7840b48727 fix: missing unicode-range 2021-07-11 15:11:12 +01:00
David Ralph
401baa6653 fix: noscript message css, remove woff from build 2021-07-11 15:08:35 +01:00
David Ralph
70fc204e70 perf: optimise search and autocomplete 2021-07-11 14:29:32 +01:00
David Ralph
a01d778f65 perf: new date picker and add purecomponent to more things 2021-07-10 21:59:53 +01:00
David Ralph
ff3e2caf49 build: fix vercel dev builds and mention vercel in readme 2021-07-06 19:42:58 +01:00
David Ralph
95614a383f fix: welcome svg, privacy welcome tab, marketplace optimisations, various widget fixes etc
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-07-06 19:38:20 +01:00
David Ralph
44fc24951f fix: import settings on welcome, progress bar, custom js etc 2021-07-04 12:28:28 +01:00
David Ralph
19bc802f09 feat: navbar hot reload, quick links zoom, add example images to welcome modal, fixes 2021-07-03 14:48:49 +01:00
David Ralph
ba9f2e01c8 perf: optimise svg 2021-07-02 22:04:11 +01:00
David Ralph
8ece0a7eb0 feat(translations): add translation support to welcome modal, fix clock 2021-07-02 21:59:58 +01:00
David Ralph
d91490874c fix: add that fix for minutes, not just seconds 2021-07-02 21:42:10 +01:00
David Ralph
6a3a367cda fix: close #164 2021-07-02 21:39:25 +01:00
dependabot[bot]
84e6532a80 chore(deps-dev): bump mini-css-extract-plugin from 1.6.2 to 2.0.0 (#163)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 1.6.2 to 2.0.0.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v1.6.2...v2.0.0)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-02 21:32:00 +01:00
David Ralph
cf36ced2a7 feat: new welcome modal, refactor many things, various bug fixes, use material-ui v5 etc
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-07-02 21:29:33 +01:00
David Ralph
c6b65f943a fix: various settings bug fixes and style changes 2021-06-30 15:25:34 +01:00
David Ralph
6aa1c6b0ea fix: weather with offline mode, maximise fixes, voice search hot reload 2021-06-30 14:11:45 +01:00
David Ralph
2dcaa5270d feat: locally store stats so users can see them (no ui yet) 2021-06-30 11:27:54 +01:00
David Ralph
1d44b2792e chore: update readme 2021-06-23 12:19:12 +01:00
David Ralph
d0577ded59 chore: revert other changes 2021-06-23 12:00:12 +01:00
David Ralph
ae5a07c756 build: revert changes 2021-06-23 11:57:36 +01:00
David Ralph
5d3418a8af build: optimise production builds, automate creating zip files 2021-06-22 21:07:56 +01:00
David Ralph
50353c9e49 build: cleanup webpack config 2021-06-22 19:45:13 +01:00
David Ralph
ea850fae56 perf: replace react-device-detect with custom code and allow edge to use voice search 2021-06-22 12:41:25 +01:00
dependabot[bot]
ba11ac171e chore(deps-dev): bump sass-loader from 7.3.1 to 12.1.0 (#162)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 7.3.1 to 12.1.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v7.3.1...v12.1.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-22 11:47:24 +01:00
David Ralph
faace9012a feat: add experimental send event feature 2021-06-22 11:46:08 +01:00
David Ralph
90ebfeedc5 chore: release 5.1.1 2021-06-22 10:19:37 +01:00
David Ralph
cfc56c6abf fix: urgent fix for background blur 2021-06-22 10:17:51 +01:00
David Ralph
d7784e7414 chore: update events 2021-06-21 23:03:47 +01:00
David Ralph
7990286e9a style: cleanup constants 2021-06-21 17:45:06 +01:00
David Ralph
f7c39eeebb feat: add opt-in umami analytics (WIP) 2021-06-21 17:42:14 +01:00
David Ralph
4449957fe6 chore: release 5.1.0 2021-06-21 13:26:31 +01:00
David Ralph
5b00b3d859 fix: voice search no longer redirects on empty and now has reload warning 2021-06-21 13:13:16 +01:00
David Ralph
aad568bd28 fix: autocomplete now works on extension, hot reload warnings added for background quality and gradient 2021-06-21 12:26:22 +01:00
David Ralph
4e1347ad4e chore: update manifest 2021-06-20 21:46:48 +01:00
David Ralph
8073d8325a fix(translations): zh-CN merge errors fixed 2021-06-20 21:08:23 +01:00
Austin Huang
dc1f1fab45 Update zh-CN translations (#161)
* Update zh_CN.json

* Update zh_CN.json

Co-authored-by: David Ralph <ohlookitsderpy@protonmail.com>
2021-06-20 20:58:54 +01:00
David Ralph
dc442ef917 fix: upgrading from 5.0.1 to latest now works, code style changes etc 2021-06-20 13:09:41 +01:00
David Ralph
796896571d feat: add support for google favicon to quick links 2021-06-18 12:40:46 +01:00
David Ralph
cad3f53140 feat(translations): added translation support to weather visibility 2021-06-17 13:08:04 +01:00
David Ralph
b0da5cfa75 feat: language support for weather description 2021-06-16 23:30:50 +01:00
Vicente
c2ca979971 feat(translations): added the missing ones (#160)
* feat(translations): updated spanish translation

* feat(translations): added the missing ones
2021-06-16 12:46:33 +01:00
Vicente
1e5f288d42 feat(translations): updated spanish translation (#159) 2021-06-16 12:31:39 +01:00
David Ralph
b2c94924a2 Merge branch 'main' of https://github.com/mue/mue 2021-06-16 12:05:15 +01:00
David Ralph
de1797c662 fix: background hot reload, settings issue, remove navbar hover setting 2021-06-16 12:05:03 +01:00
dependabot[bot]
db3081efc5 chore(deps): bump react-modal from 3.14.2 to 3.14.3 (#158)
Bumps [react-modal](https://github.com/reactjs/react-modal) from 3.14.2 to 3.14.3.
- [Release notes](https://github.com/reactjs/react-modal/releases)
- [Changelog](https://github.com/reactjs/react-modal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reactjs/react-modal/compare/v3.14.2...v3.14.3)

---
updated-dependencies:
- dependency-name: react-modal
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-16 10:11:32 +01:00
David Ralph
dcddd78164 feat: api background quality setting 2021-06-13 16:36:43 +01:00
David Ralph
335a6864b1 fix: custom js, reminder on reset button etc 2021-06-13 13:47:18 +01:00
dependabot[bot]
1f6dc34ee6 chore(deps-dev): bump sass-loader from 11.1.1 to 12.0.0 (#156)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 11.1.1 to 12.0.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v11.1.1...v12.0.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-02 10:15:14 +01:00
dependabot[bot]
fbc9189cba chore(deps): bump react-modal from 3.13.1 to 3.14.2 (#155)
Bumps [react-modal](https://github.com/reactjs/react-modal) from 3.13.1 to 3.14.2.
- [Release notes](https://github.com/reactjs/react-modal/releases)
- [Changelog](https://github.com/reactjs/react-modal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reactjs/react-modal/compare/v3.13.1...v3.14.2)

---
updated-dependencies:
- dependency-name: react-modal
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-02 10:15:03 +01:00
David Ralph
586b6f8700 style: cleanup some things 2021-05-26 22:28:26 +01:00
David Ralph
1d6013f738 fix: background location info works properly on unsplash and pexels now 2021-05-24 22:01:54 +01:00
David Ralph
c1ef3e3528 fix: small modal and marketplace css fixes 2021-05-24 11:43:38 +01:00
David Ralph
4b57229396 fix: custom quote hot reload 2021-05-24 10:44:20 +01:00
David Ralph
e721babcf7 fix: marketplace sort and widget zoom breaking analogue clock 2021-05-23 12:24:58 +01:00
David Ralph
8a816516c9 chore: cleanup readme slightly and update some content 2021-05-22 23:06:56 +01:00
David Ralph
bd09542b34 Merge branch 'main' of https://github.com/mue/mue 2021-05-22 22:56:33 +01:00
David Ralph
84dad33548 style: code cleanup and about tab changes 2021-05-22 22:56:24 +01:00
David Ralph
588021cf92 chore: update readme intro 2021-05-22 14:57:10 +01:00
David Ralph
6a9eccaed0 chore: mue edge is now updated 2021-05-21 10:33:34 +01:00
David Ralph
299547842a fix: safari css fixes 2021-05-20 15:58:06 +01:00
David Ralph
ba2dc61a5d fix: css fixes for firefox and safari, fix widget order css 2021-05-20 12:27:52 +01:00
David Ralph
2fd2e06bac fix: duckduckgo proxy no longer breaks offline mode 2021-05-16 21:05:56 +01:00
David Ralph
08bfa2772d feat: show navbar on hover setting, fix photo information toggle hot reload
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-05-09 22:39:45 +01:00
David Ralph
9b9c2e74f6 feat: add photo information icon toggle option and optimise font 2021-05-09 16:37:28 +01:00
David Ralph
63e49b79cd feat: favourite background now shows all photo info 2021-05-08 17:12:02 +01:00
David Ralph
da6ebb8c60 fix: maximise with background filters, css fixes
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-05-08 13:47:09 +01:00
David Ralph
b1fbaa7601 fix: search button and refactor wind direction icon slightly 2021-05-08 10:58:17 +01:00
David Ralph
7327382497 feat: widget zoom for weather and fixes 2021-05-07 13:27:28 +01:00
David Ralph
cb129238cb fix: improvements and fixes to about tab and photoinformation 2021-05-06 18:30:57 +01:00
David Ralph
2ac08a7cf6 chore: stop vercel from commenting on each commit 2021-05-06 18:13:00 +01:00
David Ralph
eeb0870feb fix: proper support for pexels 2021-05-06 17:30:13 +01:00
David Ralph
260d1928d8 style: code changes etc 2021-05-05 15:44:39 +01:00
David Ralph
fa19570c36 fix: various marketplace fixes 2021-05-03 15:39:34 +01:00
David Ralph
ed76fcccc8 fix: preset settings now work 2021-05-03 12:05:21 +01:00
David Ralph
6b4922b825 perf: marketplace cleanup 2021-05-03 11:27:52 +01:00
David Ralph
1dc5e7375b fix: search bar and add quote pack api support back 2021-05-03 11:10:04 +01:00
David Ralph
7628e769be fix: quote fixes and light theme search bar 2021-05-03 10:50:00 +01:00
David Ralph
7470ca9e3a feat: finish quote pack support, change quote settings ui and improve hot reload 2021-05-02 22:45:29 +01:00
David Ralph
f49cf1f65b fix: quote packs, add preset settings to sidebar (WIP) 2021-05-02 18:12:03 +01:00
David Ralph
f21ee5c5ba fix: various bug fixes for background and marketplace 2021-05-02 17:10:20 +01:00
David Ralph
5ea158c21d fix: revert css change 2021-05-02 17:01:20 +01:00
David Ralph
3aa17f0c30 fix: add missing translations 2021-05-02 14:45:34 +01:00
David Ralph
e8698f2141 feat: sort addons/marketplace items 2021-05-02 14:44:23 +01:00
David Ralph
9b5946038a feat: background filters 2021-05-02 13:40:11 +01:00
David Ralph
31a666fe22 feat: individual widget zoom, hot reload for font and custom js/css etc 2021-05-02 12:11:07 +01:00
David Ralph
b9663831fd fix: search autocomplete, add visibility to weather 2021-05-01 22:27:44 +01:00
David Ralph
48268111d0 Merge pull request #154 from Vicente015/fix-photo-info
feat: Improve photo packs text and information
2021-05-01 22:08:55 +01:00
Vicente
af335adc23 feat: Add photo location in photo packs 2021-05-01 21:35:41 +01:00
Vicente
e88cd0b765 fix: remove Unsplash text from photo packs 2021-05-01 21:33:07 +01:00
David Ralph
a1b6832747 feat: autocomplete for search
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-05-01 18:29:07 +01:00
David Ralph
7942c367a7 feat: finish lightbox
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2021-05-01 12:31:46 +01:00
David Ralph
f2f683201d fix: weather auto location not working on firefox 2021-05-01 11:45:12 +01:00
David Ralph
84dbe5cb69 feat: pexels background api 2021-04-30 22:49:04 +01:00
David Ralph
90927c9e8f fix: update check in about page 2021-04-30 18:58:58 +01:00
David Ralph
1af688c489 fix: add setting for cloudiness and fix strings 2021-04-30 18:44:03 +01:00
David Ralph
1715e7d089 feat: Auto location for weather, option to show text for weather, wind direction option etc 2021-04-30 18:19:36 +01:00
179 changed files with 8807 additions and 3596 deletions

View File

@@ -5,4 +5,4 @@ indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
insert_final_newline = true

View File

@@ -1,4 +1,4 @@
module.exports = {
extends: 'react-app',
parser: '@babel/eslint-parser'
extends: 'react-app',
parser: '@babel/eslint-parser'
};

View File

@@ -0,0 +1,20 @@
---
name: Feature Request
about: Request things to be added to mue
title: "[Feature Request]"
labels: enhancement
assignees: ''
---
**Description**
A clear and concise description of what you want adding to Mue. If it's related to a problem, mention so.
**Expected behaviour**
A clear and concise description of what you expected to happen.
**Design**
Images or Figma prototypes of what your idea would be like.
**Additional context**
Add any other context about the feature request here.

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ yarn-error.log
.eslintcache
stats.json
yarn.lock
*.zip

View File

@@ -1,30 +1,28 @@
<img src="https://raw.githubusercontent.com/mue/branding/master/logo/logo_round.png" align="left" width="180px" height="180px"/>
<img src="https://raw.githubusercontent.com/mue/branding/main/logo/logo_round.png" align="left" width="180px" height="180px"/>
<img align="left" width="0" height="192px" hspace="10"/>
> <a href="https://muetab.com/">Mue</a>
[![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)]()
[![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)]()
<br>
[![Microsoft Edge](https://img.shields.io/badge/dynamic/json?style=flat-square&label=microsoft%20edge&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Faepnglgjfokepefimhbnibfjekidhmja)](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja) [![Firefox](https://img.shields.io/amo/v/mue?label=firefox&style=flat-square)](https://addons.mozilla.org/firefox/addon/mue) [![Chrome](https://img.shields.io/chrome-web-store/v/bngmbednanpcfochchhgbkookpiaiaid?label=chrome&style=flat-square)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
Mue is a fast, open and free-to-use browser extension that gives a new, fresh and customizable tab page to most modern browsers
Mue is a fast, open and free-to-use browser extension that gives a new, fresh and customisable tab page to modern browsers.
<br>
## Table of contents
* [Screenshot](#screenshot)
* [Screenshots](#screenshot)
* [Features](#features)
* [Planned Features](#planned-features)
* [Installation](#installation)
* [Chrome](#chrome)
* [Firefox](#firefox)
* [Edge Chromium](#edge-chromium)
* [Naver](#naver)
* [Whale](#whale)
* [Other](#other)
* [Contributing](#development)
* [Requirements](#requirements)
* [Starting](#starting)
* [Building](#building)
* [Translations](#translations)
* [Credits](#credits)
* [Developers](#developers)
* [Translators](#translators)
@@ -38,17 +36,17 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
* Fast and free
* Supports multiple browsers
* Actively developed and open source
* Automatically updating API (no tracking) with new photos, quotes and offline mode
* Widgets such as searchbar, weather, quick links, clock, date, quote, greeting
* Automatically updating [API](https://github.com/mue/api) with new photos, quotes and offline mode
* Widgets such as search bar, weather, quick links, clock, date, quote, greeting
* Settings - enable/disable various features and customise parts of Mue
* Navbar with copy button, favourite background, notes feature etc
* Marketplace - download custom photo packs made by the community
* [Marketplace](https://github.com/mue/marketplace) - download custom photo packs, quote packs and preset settings made by the community
### Planned Features
Please see our [roadmap](https://github.com/mue/mue/projects)
Please see our [roadmap](https://trello.com/b/w7zhS7Hi/mue-50).
## Installation
*A demo of the tab can be found [here](https://demo.muetab.com)*
*A demo of the tab can be found [here](https://demo.muetab.com), and the latest GitHub commit build [here](https://mue.vercel.app)*
### Chrome
[![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
<br>
@@ -60,76 +58,38 @@ Please see our [roadmap](https://github.com/mue/mue/projects)
[Firefox Add-ons](https://addons.mozilla.org/firefox/addon/mue)
### Edge (Chromium)
~~[Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja)~~ Currently outdated, please use the Chrome Web Store version
[Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja)
### Naver
### Whale
[Whale Store](https://store.whale.naver.com/detail/ecllekeilcmicbfkkiknfdddbogibbnc)
### Other
Please note that we have dropped support for Opera as of Mue 5.0
[GitHub Releases](https://github.com/mue/mue/releases)
## Development
### Requirements
* [Git](https://git-scm.com/)
* [Node.JS](https://nodejs.org/)
* 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. Code your heart out! (See the sections below for how to build the extension)
### Building
<details>
<summary><b>Chrome/Edge (Chromium)</b> (Click to expand)</summary>
<ol>
<li> <code>yarn run build</code> or <code>npm run build</code>
<li> <code>yarn run chrome</code> or <code>npm run chrome</code>
<li> Visit <code>chrome://extensions</code> in Chrome
<li> Click <b>Load unpacked</b> (Make sure <b>Developer Mode</b> is on)
<li> Go to the directory containing the built copy of Mue and click <b>ok</b>
<li> Enjoy your new tab!
</ol>
</details>
<details>
<summary><b>Firefox</b> (Click to expand)</summary>
<ol>
<li> <code>yarn run build</code> or <code>npm run build</code>
<li> <code>yarn run firefox</code> or <code>npm run firefox</code>
<li> Visit <code>about:debugging#addons</code> in Firefox
<li> Click <b>Load Temporary Add-on</b>
<li> Go to the directory containing Mue and click on the <b>manifest.json</b>
<li> Enjoy your new tab!
</ol>
</details>
<details>
<summary><b>Other</b> (Click to expand)</summary>
<i>Note: To get the full new tab experience, set your browser to open the <code>index.html</code> on startup and tab open!</i>
<ol>
<li> <code>yarn run build</code> or <code>npm run build</code>
<li> Open the <code>index.html</code> in your browser
<li> Enjoy your new tab!
</ol>
</details>
Please see the [documentation](https://docs.muetab.com/development#mue-tab).
### Translations
Please see the [documentation](https://docs.muetab.com/translations).
## Credits
### Developers
[David Ralph](https://github.com/davidjcralph) - Lead development, photographer <br/>
[David Ralph](https://github.com/davidcralph) - Lead development, photographer <br/>
[Alex Sparkes](https://github.com/alexsparkes) - Name, lead design, photographer <br/>
[Isaac Saunders](https://github.com/eartharoid) - QA, development, photographer <br/>
[Wessel Tip](https://github.com/Wessel) - Development <br/>
### Translators
[Wessel Tip](https://github.com/Wessel), [Heimen Stoffels](https://github.com/Vistaus) - Dutch<br/>
[Alex Sparkes](https://github.com/alexsparkes), [Maxime](https://github.com/exiam) - French<br/>
[Anders](https://github.com/FuryingFox) - Norwegian<br/>
[Pronin Egor](https://github.com/MrZillaGold) - Russian<br/>
[Vicente](https://github.com/Vicente015) - Spanish<br/>
[Austin Huang](https://github.com/austinhuang0131) - Chinese (Simplified)<br/>
[FreeFun](https://github.com/xXFreeFunXx) - German<br/>
[Wessel Tip](https://github.com/Wessel), [Heimen Stoffels](https://github.com/Vistaus) - Dutch <br/>
[Alex Sparkes](https://github.com/alexsparkes), [Maxime](https://github.com/exiam) - French <br/>
[Anders](https://github.com/FuryingFox) - Norwegian <br/>
[Pronin Egor](https://github.com/MrZillaGold) - Russian <br/>
[Vicente](https://github.com/Vicente015) - Spanish <br/>
[Austin Huang](https://github.com/austinhuang0131) - Chinese (Simplified) <br/>
[FreeFun](https://github.com/xXFreeFunXx) - German <br/>
### Contributors
Many thanks to [Highholding](https://discord.bio/p/highholding), [Noa Shapira](#), [Roee Lupo](https://github.com/RoeeLupo), [Jeroen](#), [Gio](#), [Anders](https://github.com/FuryingFox), [Oded Shapira](https://twitter.com/dondishdev), Jacob Tyrrell and [Nikka Lai](#) for letting us use their wonderful photographs.
Many thanks to the photographers [here](https://api.muetab.com/images/photographers) for letting us use their wonderful photographs.
And finally, a big thank you to all the other [contributors](https://github.com/mue/mue/graphs/contributors)!
### Resources
[Pexels](https://pexels.com), [Unsplash](https://unsplash.com) - Stock photos used for offline mode
[Pexels](https://pexels.com), [Unsplash](https://unsplash.com) - Stock photos used for offline mode <br/>
[Undraw](https://undraw.co) - Welcome modal images

View File

@@ -1,6 +1,6 @@
module.exports = {
presets: ['@babel/preset-env', ['@babel/preset-react', {
'runtime': 'automatic'
runtime: 'automatic'
}]],
plugins: ['@babel/plugin-proposal-class-properties', '@babel/transform-runtime', 'babel-plugin-transform-react-class-to-function', '@babel/plugin-transform-react-constant-elements']
plugins: ['@babel/plugin-proposal-class-properties', '@babel/transform-runtime', '@babel/plugin-transform-react-inline-elements', 'babel-plugin-transform-react-class-to-function', '@babel/plugin-transform-react-constant-elements']
};

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,8 @@
{
"name": {
"message": "Mue"
},
"description": {
"message": "Fast, open and free-to-use new tab page for modern browsers."
}
}

View File

@@ -0,0 +1,10 @@
/* eslint-disable no-undef */
chrome.runtime.setUninstallURL('https://muetab.com/uninstall');
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
chrome.tabs.create({
url: chrome.runtime.getURL('index.html')
});
}
});

View File

@@ -0,0 +1,10 @@
/* eslint-disable no-undef */
browser.runtime.setUninstallURL('https://muetab.com/uninstall');
browser.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
browser.tabs.create({
url: browser.runtime.getURL('index.html')
});
}
});

View File

@@ -1,9 +1,11 @@
{
"manifest_version": 2,
"offline_enabled": true,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for modern browsers.",
"version": "5.0.1",
"default_locale": "en",
"name": "__MSG_name__",
"description": "__MSG_description__",
"version": "6.0.0",
"homepage_url": "https://muetab.com",
"browser_action": {
"default_icon": "icons/128x128.png"
},
@@ -14,5 +16,10 @@
"16": "icons/16x16.png",
"48": "icons/48x48.png",
"128": "icons/128x128.png"
},
"content_security_policy": "script-src 'self' https://api.bing.com https://www.google.com; object-src 'self'",
"background": {
"persistent": false,
"scripts": [ "background-chrome.js" ]
}
}

View File

@@ -2,14 +2,21 @@
"manifest_version": 2,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for modern browsers.",
"version": "5.0.1",
"version": "6.0.0",
"homepage_url": "https://muetab.com",
"browser_action": {
"default_icon": "icons/128x128.png"
},
"chrome_url_overrides": {
"newtab": "index.html"
},
"icons": {
"16": "icons/16x16.png",
"48": "icons/48x48.png",
"128": "icons/128x128.png"
},
"chrome_settings_overrides": {
"homepage": "index.html"
}
},
"content_security_policy": "script-src 'self' https://api.bing.com https://www.google.com; object-src 'self'"
}

View File

@@ -9,52 +9,56 @@
"homepage": "https://muetab.com",
"bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D",
"license": "BSD-3-Clause",
"version": "5.0.1",
"version": "6.0.0",
"dependencies": {
"@fontsource/lexend-deca": "^4.2.3",
"@fontsource/montserrat": "^4.2.2",
"@material-ui/core": "4.11.4",
"@material-ui/icons": "4.11.2",
"@eartharoid/i18n": "^1.0.2",
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@fontsource/lexend-deca": "4.4.5",
"@fontsource/montserrat": "4.4.5",
"@mui/icons-material": "5.1.1",
"@mui/material": "5.1.1",
"react": "17.0.2",
"react-clock": "3.0.0",
"react-color-gradient-picker": "0.1.2",
"react-day-picker": "7.4.10",
"react-device-detect": "1.17.0",
"react-dom": "17.0.2",
"react-modal": "3.13.1",
"react-hot-keys": "2.7.1",
"react-modal": "3.14.4",
"react-sortable-hoc": "2.0.0",
"react-toastify": "7.0.4",
"react-toastify": "8.1.0",
"weather-icons-react": "1.2.0"
},
"devDependencies": {
"@babel/core": "^7.13.16",
"@babel/eslint-parser": "^7.13.14",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-transform-react-constant-elements": "^7.13.13",
"@babel/plugin-transform-runtime": "^7.13.15",
"@babel/preset-env": "^7.13.15",
"@babel/preset-react": "^7.13.13",
"babel-loader": "^8.2.2",
"@babel/core": "^7.16.0",
"@babel/eslint-parser": "^7.16.3",
"@babel/plugin-proposal-class-properties": "^7.16.0",
"@babel/plugin-transform-react-constant-elements": "^7.16.0",
"@babel/plugin-transform-react-inline-elements": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"@babel/preset-react": "^7.16.0",
"@eartharoid/deep-merge": "^0.0.2",
"babel-loader": "^8.2.3",
"babel-plugin-transform-react-class-to-function": "^1.2.2",
"copy-webpack-plugin": "^8.1.1",
"css-loader": "^5.2.4",
"eslint": "^7.25.0",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^6.5.1",
"eslint": "^8.2.0",
"eslint-config-react-app": "^6.0.0",
"eslint-webpack-plugin": "^2.5.4",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^1.5.1",
"sass": "^1.32.11",
"sass-loader": "^11.0.1",
"source-map-loader": "^2.0.1",
"webpack": "^5.36.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2"
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.4.4",
"sass": "^1.43.4",
"sass-loader": "^12.3.0",
"source-map-loader": "^3.0.0",
"webpack": "^5.63.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
},
"scripts": {
"start": "webpack serve",
"updatetranslations": "cd scripts && node updatetranslations.js",
"build": "webpack --mode=production",
"chrome": "cp manifest/chrome.json build/manifest.json",
"firefox": "cp manifest/firefox.json build/manifest.json"
"chrome": "cp manifest/chrome.json build/manifest.json && cp -r manifest/_locales build/_locales && cp manifest/background-chrome.js build/background-chrome.js",
"firefox": "rm -rf build/_locales && cp manifest/firefox.json build/manifest.json"
},
"browserslist": {
"production": [

View File

@@ -0,0 +1 @@
<svg width="783" height="702" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="m400.51 1.53-25.446 6.562L61.56 88.94 36.113 95.5a48.18 48.18 0 0 0-34.582 58.618l110.341 427.877a48.183 48.183 0 0 0 22.157 29.413 48.183 48.183 0 0 0 36.46 5.17l.066-.017 364.265-93.936.066-.017a48.18 48.18 0 0 0 34.583-58.618L459.128 36.113A48.18 48.18 0 0 0 400.51 1.53z" fill="#F2F2F2"/><path d="m403.969 14.945-30.139 7.773-304.119 78.426-30.139 7.772a34.312 34.312 0 0 0-24.627 41.743l110.341 427.878a34.307 34.307 0 0 0 41.743 24.627l.065-.017L531.36 509.21l.066-.017a34.308 34.308 0 0 0 24.627-41.743L445.712 39.573a34.31 34.31 0 0 0-41.743-24.628z" fill="#fff"/><path d="m381.212 153.503-184.273 47.521a8.016 8.016 0 0 1-9.761-5.759 8.014 8.014 0 0 1 5.759-9.762l184.273-47.52a8.012 8.012 0 0 1 9.754 5.761 8.01 8.01 0 0 1-5.752 9.759zM419.977 171.439l-216.284 55.775a8.01 8.01 0 0 1-9.761-5.759 8.011 8.011 0 0 1 5.759-9.761l216.284-55.775a8.011 8.011 0 0 1 9.761 5.759 8.012 8.012 0 0 1-5.759 9.761zM411.48 270.877l-184.273 47.52a8.014 8.014 0 0 1-4.003-15.52l184.273-47.521a8.014 8.014 0 0 1 4.003 15.521zM450.245 288.813l-216.284 55.775a8.014 8.014 0 0 1-4.003-15.521l216.284-55.775a8.015 8.015 0 0 1 4.003 15.521zM441.748 388.25l-184.273 47.521a8.017 8.017 0 0 1-9.756-5.761 8.011 8.011 0 0 1 5.753-9.76l184.273-47.52a8.014 8.014 0 0 1 4.003 15.52zM480.513 406.186l-216.284 55.775a8 8 0 0 1-6.077-.854 8.019 8.019 0 0 1-3.866-8.027 8.01 8.01 0 0 1 3.121-5.284 8.006 8.006 0 0 1 2.82-1.355l216.284-55.775a8.011 8.011 0 0 1 9.761 5.759 8.012 8.012 0 0 1-5.759 9.761z" fill="#F2F2F2"/><path d="m165.481 249.749-65.212 16.817a3.847 3.847 0 0 1-4.68-2.762l-14.97-58.048a3.845 3.845 0 0 1 2.761-4.681l65.213-16.817a3.85 3.85 0 0 1 4.68 2.762l14.97 58.048a3.846 3.846 0 0 1-2.762 4.681zM195.749 367.122l-65.212 16.817a3.845 3.845 0 0 1-4.681-2.761l-14.97-58.048a3.854 3.854 0 0 1 .413-2.912 3.853 3.853 0 0 1 2.349-1.769l65.212-16.817a3.849 3.849 0 0 1 4.681 2.761l14.969 58.049a3.847 3.847 0 0 1-2.761 4.68zM226.019 484.496l-65.213 16.817a3.846 3.846 0 0 1-4.681-2.762l-14.969-58.048a3.846 3.846 0 0 1 2.761-4.681l65.213-16.817a3.85 3.85 0 0 1 4.681 2.762l14.969 58.048a3.846 3.846 0 0 1-2.761 4.681zM654.658 109.992H278.34a48.179 48.179 0 0 0-48.125 48.125v441.876a48.176 48.176 0 0 0 48.125 48.125h376.318a48.184 48.184 0 0 0 48.125-48.125V158.117a48.179 48.179 0 0 0-48.125-48.125z" fill="#E6E6E6"/><path d="M654.658 123.846H278.339a34.309 34.309 0 0 0-34.271 34.271v441.876a34.312 34.312 0 0 0 34.271 34.27h376.319a34.309 34.309 0 0 0 34.271-34.27V158.117a34.309 34.309 0 0 0-34.271-34.271z" fill="#fff"/><path d="M694.194 701.88c48.519 0 87.85-39.332 87.85-87.85 0-48.519-39.331-87.851-87.85-87.851-48.518 0-87.85 39.332-87.85 87.851 0 48.518 39.332 87.85 87.85 87.85z" fill="#5352ED"/><path d="M598.022 366.656H407.72a8.018 8.018 0 0 1-8.023-8.015 8.021 8.021 0 0 1 2.351-5.67 8.005 8.005 0 0 1 5.672-2.344h190.302a8.016 8.016 0 0 1 0 16.029zM631.08 393.703H407.72a8.017 8.017 0 0 1-7.412-4.945 8.021 8.021 0 0 1 0-6.138 8.008 8.008 0 0 1 4.343-4.338 8.017 8.017 0 0 1 3.069-.607h223.36a8.013 8.013 0 1 1 0 16.028zM598.022 487.869H407.72a8.017 8.017 0 0 1-7.412-4.945 8.021 8.021 0 0 1 0-6.138 8.008 8.008 0 0 1 4.343-4.338 8.017 8.017 0 0 1 3.069-.607h190.302a8.013 8.013 0 1 1 0 16.028zM631.08 514.917H407.72a8.018 8.018 0 0 1-8.023-8.014 8.014 8.014 0 0 1 8.023-8.015h223.36a8.027 8.027 0 0 1 5.673 2.344 8.02 8.02 0 0 1 0 11.341 8.016 8.016 0 0 1-5.673 2.344zM365.093 405.982h-67.346a3.847 3.847 0 0 1-3.843-3.843v-59.947a3.847 3.847 0 0 1 3.843-3.843h67.346a3.847 3.847 0 0 1 3.843 3.843v59.947a3.85 3.85 0 0 1-3.843 3.843zM365.093 527.195h-67.346a3.847 3.847 0 0 1-3.843-3.843v-59.947a3.847 3.847 0 0 1 3.843-3.843h67.346a3.847 3.847 0 0 1 3.843 3.843v59.947a3.847 3.847 0 0 1-3.843 3.843z" fill="#E6E6E6"/><path d="M598.234 231.721H457.932a8.015 8.015 0 1 1 0-16.028h140.302a8.015 8.015 0 1 1 0 16.028zM631.292 258.769h-173.36a8.009 8.009 0 0 1-7.404-4.948 8.005 8.005 0 0 1 0-6.133 8.011 8.011 0 0 1 7.404-4.948h173.36a8.016 8.016 0 0 1 5.667 13.681 8.016 8.016 0 0 1-5.667 2.348z" fill="#CCC"/><path d="M426.882 291.547H297.536a3.845 3.845 0 0 1-3.843-3.843V186.757a3.847 3.847 0 0 1 3.843-3.843h129.346a3.847 3.847 0 0 1 3.843 3.843v100.947a3.843 3.843 0 0 1-1.127 2.716 3.843 3.843 0 0 1-2.716 1.127z" fill="#5352ED"/><path d="M700.5 648v-57a6.5 6.5 0 1 0-13 0v57a6.5 6.5 0 1 0 13 0z" fill="#fff" stroke="#fff" stroke-width="5"/><path d="m728.202 621.069.609-.571a6.5 6.5 0 0 0 .33-9.154l-30.362-32.861a6.5 6.5 0 0 0-9.548-.001l-30.371 32.862a6.5 6.5 0 0 0 .329 9.154l.61.571a6.498 6.498 0 0 0 9.219-.332l23.885-25.853a1.5 1.5 0 0 1 2.204 0l23.875 25.852a6.5 6.5 0 0 0 9.22.333z" fill="#fff" stroke="#fff" stroke-width="5"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h782.044v701.88H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1 @@
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="769.001" height="771.636"><path d="M769.001 0H310.286a400.77 400.77 0 0 0-5.285 65c0 219.81 178.191 398 398 398a400.7 400.7 0 0 0 66-5.45z" fill="#2f2e41"/><path d="M574.85 248.809a57.4 57.4 0 0 1-20.163-3.64 3 3 0 1 1 2.106-5.617 52.393 52.393 0 0 0 51.263-8.531c-22.038.234-43.595-10.18-54.32-26.893-6.894-10.743-9.148-23.384-6.52-36.558a65.225 65.225 0 0 1 12.09-26.277 52.051 52.051 0 0 0-36.024 54.65 3 3 0 1 1-5.971.592 58.044 58.044 0 0 1 49.792-63.138 3 3 0 0 1 2.55 5.076C554.31 154.06 545 179.402 558.787 200.888c10.878 16.95 34.283 26.644 56.928 23.58a3 3 0 0 1 2.642 4.968 58.387 58.387 0 0 1-43.507 19.373z" fill="#6c63ff"/><path d="M527.001 250a22 22 0 1 1 22-22 22.025 22.025 0 0 1-22 22zm0-38a16 16 0 1 0 16 16 16.018 16.018 0 0 0-16-16z" fill="#6c63ff"/><path d="M8.69 567.078A10.276 10.276 0 0 1 .42 554.027l7.788-26.48 11.835 2.218.509 26.967a10.276 10.276 0 0 1-11.86 10.346z" fill="#9f616a"/><path fill="#2f2e41" d="m76.996 736.132-14.793-2.219 3.698-144.235-20.71 62.132-11.095 87.281-14.054-3.698-2.959-90.979 16.273-107.252 81.363 18.492-37.723 180.478z"/><path d="M70.205 771.636a10.873 10.873 0 0 1-10.873-10.873q0-.533.052-1.064l2.297-23.354a3.428 3.428 0 0 1 1.784-2.678c4.36-2.352 8.845-1.782 13.434 1.288a3.407 3.407 0 0 1 1.48 2.429l2.623 22.098a10.873 10.873 0 0 1-10.797 12.154zM9.82 769.898a9.794 9.794 0 0 1-4.754-14.662l15.78-23.457c5.689-4.082 9.12-2.094 10.454 5.534l3.19-7.993 2.404 2.622a7.647 7.647 0 0 1 .404 9.854l-16.368 24.91a9.794 9.794 0 0 1-11.11 3.192z" fill="#2f2e41"/><circle cx="109.542" cy="375.915" r="22.19" fill="#9f616a"/><path d="M123.595 416.596 85.872 409.2c4.86-10.364 8.75-13.87 4.438-25.15h30.327c-2.675 11.683-.09 22.648 2.958 32.546z" fill="#9f616a"/><path d="m119.157 566.009-88.76-25.149c17.78-39.13 21.503-82.09 16.232-127.504a8.217 8.217 0 0 1 7.207-9.116q.15-.017.3-.03c11.578-.953 23.648-2.177 36.174-3.886l14.054 9.615 16.273-3.698c5.221 2.53 10.48 4.636 15.227 6.734a19.038 19.038 0 0 1 10.35 23.414c-14.462 43.677-24.143 86.94-27.057 129.62z" fill="#e6e6e6"/><path d="m22.261 532.724-17.012-2.22L45.55 414.38c2.05-5.907 7.134-9.104 13.323-9.988l5.918.74-4.438 68.788zM155.525 510.524a13.484 13.484 0 0 1-13.487-8.271l-16.224-39.058 13.314-48.078 3.52 2.24q.509.323 1.004.663a31.653 31.653 0 0 1 13.002 31.471l-3.472 20.361 14.323 30.753a13.484 13.484 0 0 1-11.98 9.92z" fill="#e6e6e6"/><path d="M111.248 343.027a23.564 23.564 0 0 1 10.766 3.17c.755.439.406 2.022 1.103 2.539.878.65 2.785.255 3.563 1.017a23.615 23.615 0 0 1 7.022 19.026l-1.238 12.311-2.921-3.194a30.448 30.448 0 0 0-20.305-9.97q-.497-.033-.996-.052l2.247-3.933-3.905 3.906a38.03 38.03 0 0 0-5.321.433l2.988-5.23-5.734 5.734a15.331 15.331 0 0 0-10.713 8.738l-.637 1.411-.713-11.745a23.674 23.674 0 0 1 23.154-24.182q.82-.018 1.64.02z" fill="#2f2e41"/><ellipse cx="131.877" cy="380.205" rx="1.782" ry="4.233" fill="#9f616a"/><ellipse cx="87.319" cy="378.868" rx="1.782" ry="4.233" fill="#9f616a"/><path d="M174.034 435.42a10.276 10.276 0 0 1 7.134 13.706L171.16 474.85l-11.604-3.216 1.782-26.913a10.276 10.276 0 0 1 12.696-9.302z" fill="#9f616a"/><path fill="#e6e6e6" d="m160.579 509.055-18.492-11.835 15.533-31.806 19.231 7.397-9.615 28.107-6.657 8.137z"/><path d="M173.001 409.101V284h-2v125.101a5 5 0 1 0 2 0zm-1 7.899a3 3 0 1 1 3-3 3.003 3.003 0 0 1-3 3z" fill="#3f3d56"/><path d="M170.435 164.57a4.314 4.314 0 0 1-4.314-4.315v-12.941a4.314 4.314 0 0 1 8.627 0v12.941a4.314 4.314 0 0 1-4.313 4.314zM170.435 263.787a4.314 4.314 0 0 1-4.314-4.313v-12.942a4.314 4.314 0 1 1 8.627 0v12.942a4.314 4.314 0 0 1-4.313 4.313zM200.939 177.203a4.314 4.314 0 0 1-3.05-7.364l9.15-9.15a4.314 4.314 0 0 1 6.1 6.1l-9.15 9.15a4.3 4.3 0 0 1-3.05 1.264zM130.78 247.362a4.314 4.314 0 0 1-3.05-7.364l9.15-9.15a4.314 4.314 0 0 1 6.1 6.1l-9.15 9.151a4.3 4.3 0 0 1-3.05 1.263zM226.514 207.708h-12.941a4.314 4.314 0 0 1 0-8.628h12.941a4.314 4.314 0 1 1 0 8.628zM127.296 207.708h-12.941a4.314 4.314 0 1 1 0-8.628h12.941a4.314 4.314 0 0 1 0 8.628zM210.09 247.362a4.3 4.3 0 0 1-3.05-1.263l-9.152-9.15a4.314 4.314 0 1 1 6.101-6.101l9.15 9.15a4.314 4.314 0 0 1-3.05 7.365zM139.93 177.203a4.3 4.3 0 0 1-3.05-1.263l-9.15-9.15a4.314 4.314 0 0 1 6.1-6.102l9.15 9.151a4.314 4.314 0 0 1-3.05 7.364zM170.435 229.277a25.883 25.883 0 1 1 25.883-25.883 25.912 25.912 0 0 1-25.883 25.883zm0-43.139a17.255 17.255 0 1 0 17.255 17.256 17.275 17.275 0 0 0-17.255-17.256z" fill="#6c63ff"/></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -0,0 +1 @@
<svg width="400" height="100" viewBox="0 0 629 160" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M502.973 139.536h68.977L606.438 79.8 571.95 20.064h-68.977L468.484 79.8l34.489 59.736zM56.973 138.577h68.977l34.488-59.736-34.488-59.735H56.973L22.484 78.84l34.489 59.736zM279.973 139.616h68.977l34.488-59.736-34.488-59.735h-68.977L245.484 79.88l34.489 59.736z" fill="#F2F2F2"/><path d="M357.693 159.759h-86.464a5.019 5.019 0 0 1-4.33-2.5l-43.231-74.88a5.009 5.009 0 0 1 0-5L266.899 2.5a5.02 5.02 0 0 1 4.33-2.5h86.464a5.015 5.015 0 0 1 4.33 2.5l43.231 74.879a5.009 5.009 0 0 1 0 5l-43.231 74.88a5.018 5.018 0 0 1-4.33 2.5zM271.229 2a3.008 3.008 0 0 0-2.598 1.5L225.4 78.38a3.003 3.003 0 0 0 0 3l43.231 74.88a3.011 3.011 0 0 0 2.598 1.5h86.464a3.012 3.012 0 0 0 2.597-1.5l43.232-74.88a3.003 3.003 0 0 0 0-3L360.29 3.5a2.999 2.999 0 0 0-2.597-1.5h-86.464zM134.693 159.759H48.229a5.018 5.018 0 0 1-4.33-2.5L.668 82.379a5.015 5.015 0 0 1 0-5L43.899 2.5A5.014 5.014 0 0 1 48.23 0h86.464a5.015 5.015 0 0 1 4.33 2.5l43.231 74.879a5.009 5.009 0 0 1 0 5l-43.231 74.88a5.018 5.018 0 0 1-4.33 2.5zM48.229 2a3.008 3.008 0 0 0-2.598 1.5L2.4 78.379a3.009 3.009 0 0 0 0 3l43.231 74.88a3.011 3.011 0 0 0 2.598 1.5h86.464a3.012 3.012 0 0 0 2.597-1.5l43.232-74.88a3.003 3.003 0 0 0 0-3L137.29 3.5a2.999 2.999 0 0 0-2.597-1.5H48.229zM580.693 159.759H494.23a5.013 5.013 0 0 1-4.331-2.5l-43.231-74.88a5.009 5.009 0 0 1 0-5L489.899 2.5A5.016 5.016 0 0 1 494.23 0h86.463a5.015 5.015 0 0 1 4.33 2.5l43.231 74.879a5.009 5.009 0 0 1 0 5l-43.231 74.88a5.016 5.016 0 0 1-4.33 2.5zM494.23 2a3.01 3.01 0 0 0-2.599 1.5L448.4 78.379a3.003 3.003 0 0 0 0 3l43.231 74.88a3.011 3.011 0 0 0 2.599 1.5h86.463a3.012 3.012 0 0 0 2.598-1.5l43.231-74.88a3.003 3.003 0 0 0 0-3L583.291 3.5a3.009 3.009 0 0 0-2.598-1.5H494.23z" fill="#CCC"/><path d="M91.461 45.863a32.977 32.977 0 1 0 0 65.954 32.977 32.977 0 0 0 0-65.954zm0 9.893a9.893 9.893 0 1 1 0 19.786 9.893 9.893 0 0 1 0-19.786zm0 47.626a24.026 24.026 0 0 1-19.786-10.559c.159-6.595 13.19-10.226 19.786-10.226 6.595 0 19.628 3.631 19.786 10.226a24.062 24.062 0 0 1-19.786 10.559zM314.397 56.907a17.995 17.995 0 0 0-12.604-5.58 18.005 18.005 0 0 0-12.851 31.035l26.067 26.068 25.456-25.456a18.44 18.44 0 0 0-.306-25.761 18.44 18.44 0 0 0-25.762-.306zM558.697 59.821c0 11.728-21.235 37.474-21.235 37.474s-21.235-25.746-21.235-37.474a21.223 21.223 0 0 1 6.207-15.02 21.236 21.236 0 0 1 36.263 14.985v.035z" fill="#5352ED"/><path d="M537.462 68.163a8.342 8.342 0 1 0 0-16.684 8.342 8.342 0 0 0 0 16.684z" fill="#fff"/><path d="M536.702 121.029a8.342 8.342 0 1 0 0-16.685 8.342 8.342 0 0 0 0 16.685z" fill="#5352ED"/></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1 @@
<svg width="1066" height="774" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path opacity=".1" d="M995.19 369.87c.59-6.77.9-13.65.9-20.6 0-108.83-73.84-197.06-164.92-197.06-29 0-56.34 9-80 24.75-64.47-50-148.64-80.21-240.72-80.21-149.83 0-278.71 80.07-335.89 194.9a138.6 138.6 0 0 0-9.6-.34C73.83 291.31 0 379.53 0 488.36c0 40 10 77.23 27.14 108.31 0 97.91 78.45 177.31 175.22 177.31h122l.54-.93c7.17-11.64 24.34-14.55 36.3-7.94 3.16 1.74 6.1 4 9.63 4.8 14.13 3 23.62-19.73 37.92-17.52 7.18 1.11 12.78 8.53 20 7.77 4.79-.51 8.42-4.52 12.92-6.22 7.21-2.74 14.52 1.06 19.57 7.23 2.93-8.43 2.91-18.42 7.65-26.15 7.17-11.64 24.34-14.55 36.3-7.94 3.16 1.74 6.1 4 9.63 4.8 14.13 3 23.62-19.73 37.92-17.52 7.18 1.11 12.78 8.53 20 7.77 4.79-.51 8.42-4.52 12.92-6.22 11.22-4.27 22.71 7.32 25.47 19a81.066 81.066 0 0 1 1.69 15.64c9.68-4.69 17.86-17.88 28.91-16.17 7.18 1.11 12.78 8.53 20 7.77 4.79-.51 8.42-4.52 12.92-6.22 11.22-4.27 22.71 7.32 25.47 19 1.47 6.2 1.57 12.64 1.82 19h202.15c76 0 137.58-62.32 137.58-139.2 15.42-30 24.33-65.28 24.33-103.06 0-67-28-126.2-70.81-161.8z" fill="#6C63FF"/><path d="M114 582.98v-24.3l11.2 11.2 2.8-2.9-16-16-16 16 2.8 2.8 11.2-11.1v24.3h4zM789 299a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM224 283a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM401 435a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM925 534a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM700 617a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM315 687a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM96 444a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM125 380a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM957 492a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM770 716a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM215 612a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM284 337a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM386.5 227.5H371V212h-2v15.5h-15.5v2H369V245h2v-15.5h15.5v-2zM764 513.89h-9.39v-9.39h-1.22v9.39H744v1.22h9.39v9.39h1.22v-9.39H764v-1.22zM707 688.89h-9.39v-9.39h-1.22v9.39H687v1.22h9.39v9.39h1.22v-9.39H707v-1.22zM240 666.89h-9.39v-9.39h-1.22v9.39H220v1.22h9.39v9.39h1.22v-9.39H240v-1.22zM174 490.89h-9.39v-9.39h-1.22v9.39H154v1.22h9.39v9.39h1.22v-9.39H174v-1.22zM940 667v-24.3l11.2 11.2 2.8-2.9-16-16-16 16 2.8 2.8 11.2-11.1V667h4zM747 385a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM816 618a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM807 439a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM909.5 329.5H894V314h-2v15.5h-15.5v2H892V347h2v-15.5h15.5v-2zM697 592.89h-9.39v-9.39h-1.22v9.39H677v1.22h9.39v9.39h1.22v-9.39H697v-1.22z" fill="#fff"/><path d="m258.343 592.735 3.913-4.048-2.432-2.348-3.913 4.048-15.794 8.254 10.535 10.166 7.691-16.072z" fill="#5352ED"/><path d="m268.811 603.045 4.009-4.15-2.49-2.417-4.016 4.158-16.198 8.463 10.812 10.428 7.883-16.482z" fill="#5352ED"/><path d="m279.414 613.083 3.913-4.048-2.432-2.348-3.913 4.048-15.794 8.254 10.543 10.173 7.683-16.079zM354.436 685.727l4.016-4.158-2.497-2.409-4.016 4.157-16.191 8.456 10.805 10.435 7.883-16.481zM365.242 696.161l4.016-4.157-2.498-2.41-4.016 4.158-16.191 8.456 10.805 10.434 7.884-16.481zM376.047 706.596l4.016-4.158-2.498-2.409-4.016 4.157-16.191 8.456 10.805 10.435 7.884-16.481zM305.384 638.366l4.016-4.158-2.497-2.409-4.016 4.157-16.191 8.456 10.805 10.435 7.883-16.481z" fill="#5352ED"/><path d="m316.19 648.8 4.016-4.157-2.49-2.403-4.016 4.158-16.199 8.449 10.805 10.435 7.884-16.482zM326.995 659.235l4.016-4.158-2.49-2.402-4.016 4.157-16.199 8.45 10.812 10.441 7.877-16.488zM575.105 337.375c13.499-14.624 20.646-56.373 11.545-65.16-9.102-8.787-49.749.608-63.888 14.613l-.437-.411-277.74 287.63 52.795 50.972 277.733-287.623-.008-.021zM671.535 430.49c13.499-14.623 20.646-56.373 11.545-65.16-9.102-8.787-49.749.609-63.881 14.621l-.436-.412L341.022 667.17l52.795 50.971L671.55 430.518l-.015-.028z" fill="#5352ED"/><path d="M752.018 249.005c19.93-21.3 38.411-74.794 29.317-83.574-9.094-8.78-61.104 12.332-81.634 32.984l-.429-.405-407.254 421.748 52.781 50.972 407.26-421.755-.041.03z" fill="#363192"/><g opacity=".1" fill="#000"><path opacity=".1" d="M574.87 274.92c7.59-17.71 22.41-36.18 31.63-36.07 12 .14 33.62 31.79 36.07 52l.26-21.71c-.21-19.9-23.65-55.18-36.3-55.33-9.1-.11-23.64 17.88-31.32 35.38l-.34 25.73zM435.41 291.7h.6c.67-19.89 23.81-54.61 36.45-54.46 8.26.1 21.11 15.17 29.1 31.16l1.94-162.36h.59c.78-29.16 24.13-80.2 36.77-80 11.94.14 33.36 46.21 35.78 75.9l.23-20c-.11-29.17-23.36-80.77-36-80.92-12.64-.15-36 50.89-36.77 80.05h-.59l-1.94 162.36c-8-16-20.84-31.06-29.1-31.16-12.64-.15-35.78 34.57-36.45 54.46h-.6l-4.77 399.81h.3l4.46-374.84z"/></g><path d="M540.858 25.386h-.01a6.93 6.93 0 0 0-7.012 6.847l-.192 16.189a6.93 6.93 0 0 0 6.847 7.011h.01a6.93 6.93 0 0 0 7.012-6.847l.192-16.189a6.93 6.93 0 0 0-6.847-7.011z" fill="#ECECF3"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h1066v773.96H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -11,21 +11,17 @@
<body>
<noscript>
<style>
@font-face {
font-family: 'Lexend Deca';
src: url('./static/media/lexend-deca-latin-400-normal.35a9aeba.woff2');
}
*, a {
font-family: 'Lexend Deca', sans-serif;
text-align: center;
color: black;
background: white !important;
}
@media (prefers-color-scheme: dark) {
*, a {
color: white;
background: #2f3640;
background: #2f3640 !important;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,14 @@
// tl;dr this function merges the translation file with the english file in order to add untranslated strings
const fs = require('fs');
const merge = require('@eartharoid/deep-merge');
fs.readdirSync('../src/translations').forEach((file) => {
if (file === 'en_GB.json') {
return;
}
const newdata = merge(require('../src/translations/en_GB.json'), require('../src/translations/' + file));
fs.writeFileSync('../src/translations/' + file, JSON.stringify(newdata, null, 2));
// add new line
fs.appendFileSync('../src/translations/' + file, '\n');
});

View File

@@ -1,34 +1,34 @@
import React from 'react';
import Background from './components/widgets/background/Background';
import Widgets from './components/widgets/Widgets';
import Modals from './components/modals/Modals';
import EventBus from './modules/helpers/eventbus';
import SettingsFunctions from './modules/helpers/settings';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { ToastContainer } from 'react-toastify';
export default class App extends React.PureComponent {
componentDidMount() {
if (!localStorage.getItem('firstRun')) {
SettingsFunctions.setDefaultSettings();
window.location.reload();
}
import Background from 'components/widgets/background/Background';
import Widgets from 'components/widgets/Widgets';
import Modals from 'components/modals/Modals';
import { loadSettings, moveSettings } from 'modules/helpers/settings';
import EventBus from 'modules/helpers/eventbus';
export default class App extends PureComponent {
componentDidMount() {
// 4.0 -> 5.0 (the key below is only on 5.0)
if (!localStorage.getItem('order')) {
SettingsFunctions.moveSettings();
// now featuring 5.0 -> 5.1
// the firstRun check was moved here because the old function was useless
if (!localStorage.getItem('firstRun') || !localStorage.getItem('stats')) {
moveSettings();
window.location.reload();
}
SettingsFunctions.loadSettings();
loadSettings();
EventBus.on('refresh', (data) => {
if (data === 'other') {
SettingsFunctions.loadSettings(true);
loadSettings(true);
}
});
variables.stats.tabLoad();
}
render() {

View File

@@ -0,0 +1,78 @@
import { PureComponent } from 'react';
import EventBus from 'modules/helpers/eventbus';
import './autocomplete.scss';
export default class Autocomplete extends PureComponent {
constructor(props) {
super(props);
this.state = {
filtered: [],
input: '',
autocompleteDisabled: (localStorage.getItem('autocomplete') !== 'true')
};
}
onChange = (e) => {
if (this.state.autocompleteDisabled) {
return this.setState({
input: e.target.value
});
}
this.setState({
filtered: this.props.suggestions.filter((suggestion) => suggestion.toLowerCase().indexOf(e.target.value.toLowerCase()) > -1),
input: e.target.value
});
this.props.onChange(e.target.value);
};
onClick = (e) => {
this.setState({
filtered: [],
input: e.target.innerText
});
this.props.onClick(e);
};
componentDidMount() {
EventBus.on('refresh', (data) => {
if (data === 'search') {
this.setState({
autocompleteDisabled: (localStorage.getItem('autocomplete') !== 'true')
});
}
});
}
componentWillUnount() {
EventBus.off('refresh');
}
render() {
let autocomplete = null;
// length will only be > 0 if enabled
if (this.state.filtered.length > 0 && this.state.input.length > 0) {
autocomplete = (
<ul className='suggestions'>
{this.state.filtered.map((suggestion) => (
<li key={suggestion} onClick={this.onClick}>
{suggestion}
</li>
))}
</ul>
);
}
return (
<>
<input type='text' onChange={this.onChange} value={this.state.input} placeholder={this.props.placeholder || ''} autoComplete='off' id={this.props.id || ''} />
{autocomplete}
</>
);
}
}

View File

@@ -0,0 +1,50 @@
.suggestions {
text-align: left;
font-size: calc(5px + 1.2vmin);
background-color: rgba(255, 255, 255, 0.8);
color: black;
border-top-width: 0;
list-style: none;
margin-top: 40px;
max-height: 143px;
overflow: hidden;
position: relative;
display: inline-block;
margin-left: 40px;
border-radius: 24px;
width: 430px;
opacity: 0;
li {
padding: 0.5rem;
padding-left: 20px;
&:hover {
background-color: rgba(255, 255, 255, 0.8);
cursor: pointer;
}
}
}
.searchBar {
input[type=text]:focus+.suggestions {
opacity: 1;
}
}
@media screen and (min-width: 1400px) {
.suggestions {
margin-top: 50px;
}
}
.dark .suggestions {
background-color: rgba(0, 0, 0, 0.5);
color: white;
li {
&:hover {
background-color: rgba(0, 0, 0, 0.5);
}
}
}

View File

@@ -0,0 +1,15 @@
import variables from 'modules/variables';
import './preview.scss';
export default function Preview(props) {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<div className='preview-mode'>
<h3>{getMessage('modals.main.settings.reminder.title')}</h3>
<h1>{getMessage('modals.welcome.preview.description')}</h1>
<button className='close' onClick={() => props.setup()}>{getMessage('modals.welcome.preview.continue')}</button>
</div>
);
}

View File

@@ -0,0 +1,15 @@
.preview-mode {
position: absolute;
bottom: 20px;
right: 20px;
padding: 15px;
color: var(--modal-text);
background: var(--background);
max-width: 300px;
border-radius: 0.7em;
z-index: 999;
h1 {
font-size: 1rem;
}
}

View File

@@ -1,12 +1,10 @@
import React from 'react';
import './tooltip.scss';
export default function Tooltip(props) {
export default function Tooltip({ children, title }) {
return (
<div className='tooltip'>
{props.children}
<span className='tooltipTitle'>{props.title}</span>
{children}
<span className='tooltipTitle'>{title}</span>
</div>
);
}

View File

@@ -4,9 +4,9 @@
display: inline-block;
.tooltipTitle {
width: 60px;
min-width: 60px;
background-color: rgba(255, 255, 255, 0.89);
color: #000000;
color: #000;
text-align: center;
font-size: 0.6rem;
border-radius: 6px;
@@ -20,7 +20,7 @@
cursor: initial;
user-select: none;
opacity: 0;
transition: opacity 0.8s;
transition: 0.2s;
}
&:hover {
@@ -33,5 +33,5 @@
.dark .tooltipTitle {
background-color: rgba(0, 0, 0, 0.79);
color: #ffffff;
color: #fff;
}

View File

@@ -1,18 +1,18 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { ErrorOutline } from '@mui/icons-material';
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
export default class ErrorBoundary extends React.PureComponent {
export default class ErrorBoundary extends PureComponent {
constructor(props) {
super(props);
this.state = {
error: false
};
this.language = window.language.modals.main.error_boundary;
}
static getDerivedStateFromError(error) {
console.log(error);
variables.stats.postEvent('modal', 'Error occurred');
return {
error: true
};
@@ -23,10 +23,10 @@ export default class ErrorBoundary extends React.PureComponent {
return (
<div className='emptyitems'>
<div className='emptyMessage'>
<ErrorOutlineIcon/>
<h1>{this.language.title}</h1>
<p>{this.language.message}</p>
<button className='refresh' onClick={() => window.location.reload()}>{this.language.refresh}</button>
<ErrorOutline/>
<h1>{variables.language.getMessage(variables.languagecode, 'modals.main.error_boundary.title')}</h1>
<p>{variables.language.getMessage(variables.languagecode, 'modals.main.error_boundary.message')}</p>
<button className='refresh' onClick={() => window.location.reload()}>{variables.language.getMessage(variables.languagecode, 'modals.main.error_boundary.refresh')}</button>
</div>
</div>
);

View File

@@ -1,24 +1,28 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent, Suspense, lazy } from 'react';
import Modal from 'react-modal';
//import Hotkeys from 'react-hot-keys';
import Main from './main/Main';
import Navbar from '../widgets/navbar/Navbar';
import Preview from '../helpers/preview/Preview';
import Modal from 'react-modal';
import EventBus from 'modules/helpers/eventbus';
// These modals are lazy loaded as the user won't use them every time they open a tab
// We used to lazy load the main modal, but doing so broke the main modal open animation on first click
const Welcome = React.lazy(() => import('./welcome/Welcome'));
const Feedback = React.lazy(() => import('./feedback/Feedback'));
// Welcome modal is lazy loaded as the user won't use it every time they open a tab
// We used to lazy load the main and feedback modals, but doing so broke the modal open animation on first click
const Welcome = lazy(() => import('./welcome/Welcome'));
const renderLoader = () => <></>;
export default class Modals extends React.PureComponent {
export default class Modals extends PureComponent {
constructor() {
super();
this.state = {
mainModal: false,
updateModal: false,
welcomeModal: false,
feedbackModal: false
feedbackModal: false,
preview: false
};
}
@@ -27,6 +31,15 @@ export default class Modals extends React.PureComponent {
this.setState({
welcomeModal: true
});
variables.stats.postEvent('modal', 'Opened welcome');
}
if (window.location.search === '?nointro=true') {
if (localStorage.getItem('showWelcome') === 'true') {
localStorage.setItem('showWelcome', false);
EventBus.dispatch('refresh', 'widgets');
EventBus.dispatch('refresh', 'backgroundwelcome');
}
}
// hide refresh reminder once the user has refreshed the page
@@ -38,24 +51,46 @@ export default class Modals extends React.PureComponent {
this.setState({
welcomeModal: false
});
EventBus.dispatch('refresh', 'widgetsWelcomeDone');
EventBus.dispatch('refresh', 'widgets');
EventBus.dispatch('refresh', 'backgroundwelcome');
}
previewWelcome() {
localStorage.setItem('showWelcome', false);
localStorage.setItem('welcomePreview', true);
this.setState({
welcomeModal: false,
preview: true
});
EventBus.dispatch('refresh', 'widgetsWelcome');
}
toggleModal(type, action) {
this.setState({
[type]: action
});
if (action !== false) {
variables.stats.postEvent('modal', `Opened ${type.replace('Modal', '')}`);
}
}
render() {
return (
<>
<Navbar openModal={(modal) => this.setState({ [modal]: true })}/>
<Modal closeTimeoutMS={300} id='modal' onRequestClose={() => this.setState({ mainModal: false })} isOpen={this.state.mainModal} className='Modal' overlayClassName='Overlay' ariaHideApp={false}>
<Main modalClose={() => this.setState({ mainModal: false })}/>
{this.state.welcomeModal === false ? <Navbar openModal={(modal) => this.toggleModal(modal, true)}/> : null}
<Modal closeTimeoutMS={300} id='modal' onRequestClose={() => this.toggleModal('mainModal', false)} isOpen={this.state.mainModal} className='Modal mainModal' overlayClassName='Overlay' ariaHideApp={false}>
<Main modalClose={() => this.toggleModal('mainModal', false)}/>
</Modal>
<React.Suspense fallback={renderLoader()}>
<Modal closeTimeoutMS={300} onRequestClose={() => this.closeWelcome()} isOpen={this.state.welcomeModal} className='Modal welcomemodal' overlayClassName='Overlay' ariaHideApp={false}>
<Welcome modalClose={() => this.closeWelcome()}/>
<Suspense fallback={renderLoader()}>
<Modal closeTimeoutMS={300} onRequestClose={() => this.closeWelcome()} isOpen={this.state.welcomeModal} className='Modal welcomemodal mainModal' overlayClassName='Overlay welcomeoverlay' shouldCloseOnOverlayClick={false} ariaHideApp={false}>
<Welcome modalClose={() => this.closeWelcome()} modalSkip={() => this.previewWelcome()}/>
</Modal>
<Modal closeTimeoutMS={300} onRequestClose={() => this.setState({ feedbackModal: false })} isOpen={this.state.feedbackModal} className='Modal' overlayClassName='Overlay' ariaHideApp={false}>
<Feedback modalClose={() => this.setState({ feedbackModal: false })}/>
</Modal>
</React.Suspense>
</Suspense>
{this.state.preview ? <Preview setup={() => window.location.reload()}/> : null}
{/*variables.keybinds.toggleModal && variables.keybinds.toggleModal !== '' ? <Hotkeys keyName={variables.keybinds.toggleModal} onKeyDown={() => this.toggleModal('mainModal', (this.state.mainModal === true ? false : true))}/> : null*/}
</>
);
}
}
}

View File

@@ -1,93 +0,0 @@
import React from 'react';
import './feedback.scss';
export default class FeedbackModal extends React.PureComponent {
constructor() {
super();
this.state = {
questionone: 5,
questionthree: 5,
questiontwoerror: '',
questionfourerror: '',
formsubmit: ''
};
this.language = window.language.modals.feedback;
}
async submitForm () {
let questiontwoerror, questionfourerror;
if (document.getElementById('questiontwo').value.length <= 0) {
questiontwoerror = this.language.not_filled;
}
if (document.getElementById('questionfour').value.length <= 0) {
questionfourerror = this.language.not_filled;
}
if (questiontwoerror || questionfourerror) {
this.setState({
questiontwoerror: questiontwoerror,
questionfourerror: questionfourerror
});
} else {
this.setState({
questiontwoerror: '',
questionfourerror: ''
});
await fetch(window.constants.FEEDBACK_FORM, {
'method': 'POST'
});
this.setState({
formsubmit: this.language.success
});
setTimeout(() => {
this.props.modalClose();
}, 3000);
}
}
render() {
return (
<div className='feedback'>
<h1>{this.language.title}</h1>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<>
<input type='hidden' name='version' value={window.constants.VERSION} />
<>
<label>{this.language.question_one}</label>
<br/><br/>
<label className='values'>0</label>
<input className='range' type='range' min='0' max='10' name='question1' value={this.state.questionone} onChange={(e) => this.setState({ questionone: e.target.value })}/>
<label className='values'>10 ({this.state.questionone})</label>
</>
<br/><br/>
<>
<label>{this.language.question_two}</label>
<textarea name='question2' id='questiontwo'/>
<p className='feedbackerror'>{this.state.questiontwoerror}</p>
</>
<>
<label>{this.language.question_three}</label>
<br/><br/>
<label className='values'>0</label>
<input className='range' type='range' min='0' max='10' name='question3' value={this.state.questionthree} onChange={(e) => this.setState({ questionthree: e.target.value })}/>
<label className='values'>10 ({this.state.questionthree})</label>
</>
<br/><br/>
<>
<label>{this.language.question_four}</label>
<textarea name='question4' id='questionfour'/>
<p className='feedbackerror'>{this.state.questionfourerror}</p>
</>
{this.state.formsubmit}
<button onClick={() => this.submitForm()}>{this.language.submit}</button>
</>
</div>
);
}
}

View File

@@ -1,63 +0,0 @@
@import '../main/scss/index.scss';
#feedbackmodal {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 400px;
height: 100px;
}
.feedback {
width: 400px;
padding: 5px;
h1,
.closeModal {
font-size: 2.5em;
}
span {
font-size: 6em;
}
button {
width: 50%;
border-radius: 48px;
outline: none;
border: none;
padding: 15px 20px;
font-size: 1.5em;
background: linear-gradient(90deg, #ffb032 0%, #dd3b67 100%);
color: #fff;
text-transform: uppercase;
cursor: pointer;
}
input[type=text] {
width: 100%;
font-size: 1em;
}
input[type=range] {
margin-left: 20px;
margin-right: 20px;
vertical-align: middle;
}
label.values {
font-weight: 700;
}
textarea {
width: 80%;
background-color: var(--sidebar);
}
.feedbackerror {
color: red;
}
}

View File

@@ -1,50 +1,56 @@
import React from 'react';
import variables from 'modules/variables';
import { Suspense, lazy } from 'react';
import Tabs from './tabs/backend/Tabs';
import './scss/index.scss';
// Lazy load all the tabs instead of the modal itself
const Settings = React.lazy(() => import('./tabs/Settings'));
const Addons = React.lazy(() => import('./tabs/Addons'));
const Marketplace = React.lazy(() => import('./tabs/Marketplace'));
const Settings = lazy(() => import('./tabs/Settings'));
const Addons = lazy(() => import('./tabs/Addons'));
const Marketplace = lazy(() => import('./tabs/Marketplace'));
const renderLoader = () => (
<Tabs>
<div label={window.language.modals.main.loading}>
<div label={variables.language.getMessage(variables.languagecode, 'modals.main.loading')}>
<div className='emptyitems'>
<div className='emptyMessage'>
<h1>{window.language.modals.main.loading}</h1>
<h1>{variables.language.getMessage(variables.languagecode, 'modals.main.loading')}</h1>
</div>
</div>
</div>
<div label='' style={{ 'display': 'none' }}></div>
<div label='' style={{ display: 'none' }}></div>
</Tabs>
);
export default function MainModal(props) {
const language = window.language.modals.main.navbar;
export default function MainModal({ modalClose }) {
const display = (localStorage.getItem('showReminder') === 'true') ? 'block' : 'none';
return (
<>
<span className='closeModal' onClick={props.modalClose}>&times;</span>
<span className='closeModal' onClick={modalClose}>&times;</span>
<Tabs navbar={true}>
<div label={language.settings}>
<React.Suspense fallback={renderLoader()}>
<div label={variables.language.getMessage(variables.languagecode, 'modals.main.navbar.settings')} name='settings'>
<Suspense fallback={renderLoader()}>
<Settings/>
</React.Suspense>
</Suspense>
</div>
<div label={language.addons}>
<React.Suspense fallback={renderLoader()}>
<div label={variables.language.getMessage(variables.languagecode, 'modals.main.navbar.addons')} name='addons'>
<Suspense fallback={renderLoader()}>
<Addons/>
</React.Suspense>
</Suspense>
</div>
<div label={language.marketplace}>
<React.Suspense fallback={renderLoader()}>
<div label={variables.language.getMessage(variables.languagecode, 'modals.main.navbar.marketplace')} name='marketplace'>
<Suspense fallback={renderLoader()}>
<Marketplace/>
</React.Suspense>
</Suspense>
</div>
</Tabs>
<div className='reminder-info' style={{ display }}>
<h1>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.reminder.title')}</h1>
<p>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.reminder.message')}</p>
<button className='pinNote' onClick={() => window.location.reload()}>{variables.language.getMessage(variables.languagecode, 'modals.main.error_boundary.refresh')}</button>
</div>
</>
);
}

View File

@@ -1,74 +1,101 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent, Fragment } from 'react';
import { toast } from 'react-toastify';
import { ArrowBack } from '@mui/icons-material';
import Modal from 'react-modal';
//import Modal from 'react-modal';
import { install, uninstall } from 'modules/helpers/marketplace';
//import Lightbox from './Lightbox';
import Lightbox from './Lightbox';
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
export default class Item extends React.PureComponent {
constructor() {
super();
export default class Item extends PureComponent {
constructor(props) {
super(props);
this.state = {
showLightbox: false
showLightbox: false,
showUpdateButton: (this.props.addonInstalled === true && this.props.addonInstalledVersion !== this.props.data.version)
};
}
updateAddon() {
uninstall(this.props.data.type, this.props.data.display_name);
install(this.props.data.type, this.props.data);
toast(variables.language.getMessage(variables.languagecode, 'toasts.updated'));
this.setState({
showUpdateButton: false
});
}
render() {
const language = window.language.modals.main.marketplace.product;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
if (!this.props.data.display_name) {
return null;
}
let warningHTML;
// For some reason it breaks sometimes so we use try/catch
try {
if (this.props.content.content.data.quote_api) {
warningHTML = (
<div className='productInformation'>
<ul>
<li className='header'>{language.quote_warning.title}</li>
<li id='updated'>{language.quote_warning.description}</li>
</ul>
</div>
);
}
} catch (e) {
// ignore
if (this.props.data.quote_api) {
warningHTML = (
<div className='productInformation'>
<ul>
<li className='header'>{getMessage('modals.main.marketplace.product.quote_warning.title')}</li>
<li id='updated'>{getMessage('modals.main.marketplace.product.quote_warning.description')}</li>
</ul>
</div>
);
}
// prevent console error
let iconsrc = window.constants.DDG_PROXY + this.props.data.icon;
let iconsrc = variables.constants.DDG_IMAGE_PROXY + this.props.data.icon;
if (!this.props.data.icon) {
iconsrc = null;
}
let updateButton;
if (this.state.showUpdateButton) {
updateButton = (
<Fragment key='update'>
<br/><br/>
<button className='removeFromMue' onClick={() => this.updateAddon()}>
{getMessage('modals.main.addons.product.buttons.update_addon')}
</button>
</Fragment>
);
}
return (
<div id='item' style={{ 'display': this.props.display }}>
<div id='item'>
<br/>
<span><ArrowBackIcon className='backArrow' onClick={this.props.toggleFunction}/></span>
<ArrowBack className='backArrow' onClick={this.props.toggleFunction}/>
<br/>
<h1>{this.props.data.display_name}</h1>
{this.props.button}
<br/>
<img alt='product' draggable='false' src={iconsrc} onClick={() => this.setState({ showLightbox: true })}/>
<div className='informationContainer'>
<h1>{language.overview}</h1>
<p className='description' dangerouslySetInnerHTML={{ __html: this.props.data.description }}></p>
<div className='productInformation'>
<ul>
{/* <li className='header'>{language.last_updated}</li>
<li>{this.props.data.updated}</li>
<br/>*/}
<li className='header'>{language.version}</li>
<li>{this.props.data.version}</li>
<br/>
<li className='header'>{language.author}</li>
<li>{this.props.data.author}</li>
{updateButton}
<br/><br/>
{iconsrc ? <img alt='product' draggable='false' src={iconsrc} onClick={() => this.setState({ showLightbox: true })}/> : null}
<div className='side'>
<div className='productInformation'>
<ul>
<li className='header'>{getMessage('modals.main.marketplace.product.version')}</li>
{updateButton ? <li>{this.props.data.version} (Installed: {this.props.data.addonInstalledVersion})</li> : <li>{this.props.data.version}</li>}
<br/>
<li className='header'>{getMessage('modals.main.marketplace.product.author')}</li>
<li>{this.props.data.author}</li>
</ul>
</div>
{warningHTML}
</div>
<br/>
{warningHTML}
</div>
{/* <Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ showLightbox: false })} isOpen={this.state.showLightbox} className='Modal lightboxmodal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<div className='sidebr'>
<br/><br/>
</div>
<div className='informationContainer'>
<h1 className='overview'>{getMessage('modals.main.marketplace.product.overview')}</h1>
<p className='description' dangerouslySetInnerHTML={{ __html: this.props.data.description }}></p>
</div>
<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ showLightbox: false })} isOpen={this.state.showLightbox} className='Modal lightboxmodal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<Lightbox modalClose={() => this.setState({ showLightbox: false })} img={iconsrc}/>
</Modal> */}
</Modal>
</div>
);
}

View File

@@ -1,13 +1,13 @@
import React from 'react';
import variables from 'modules/variables';
export default function Items(props) {
export default function Items({ items, toggleFunction }) {
return (
<div className='items'>
{props.items.map((item) => (
<div className='item' onClick={() => props.toggleFunction(item.name)} key={item.name}>
<img alt='icon' draggable='false' src={window.constants.DDG_PROXY + item.icon_url} />
{items.map((item) => (
<div className='item' onClick={() => toggleFunction(item.name)} key={item.name}>
<img alt='icon' draggable='false' src={variables.constants.DDG_IMAGE_PROXY + item.icon_url} />
<div className='details'>
<h4>{item.display_name ? item.display_name : item.name}</h4>
<h4>{item.display_name || item.name}</h4>
<p>{item.author}</p>
</div>
</div>

View File

@@ -1,10 +1,12 @@
import React from 'react';
import variables from 'modules/variables';
export default function Lightbox({ modalClose, img }) {
variables.stats.postEvent('modal', 'Opened lightbox');
export default function Lightbox(props) {
return (
<>
<span className='closeModal' onClick={props.modalClose}>&times;</span>
<img src={props.img} className='lightboximg' draggable={false} alt='Item'/>
<span className='closeModal' onClick={modalClose}>&times;</span>
<img src={img} className='lightboximg' draggable={false} alt='Item screenshot'/>
</>
);
}

View File

@@ -0,0 +1,20 @@
import variables from 'modules/variables';
import { Close } from '@mui/icons-material';
export default function SideloadFailedModal({ modalClose, reason }) {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<>
<h1>{getMessage('modals.main.error_boundary.title')}</h1>
<span>{getMessage('modals.main.addons.sideload.failed')}</span>
<br/><br/>
<span>{reason}</span>
<div className='resetfooter'>
<button className='round import' style={{ marginLeft: '-30px' }} onClick={modalClose}>
<Close/>
</button>
</div>
</>
);
}

View File

@@ -1,36 +1,27 @@
import React from 'react';
import LocalMallIcon from '@material-ui/icons/LocalMall';
import Item from '../Item';
import Items from '../Items';
import MarketplaceFunctions from '../../../../../modules/helpers/marketplace';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { LocalMall } from '@mui/icons-material';
import { toast } from 'react-toastify';
export default class Added extends React.PureComponent {
import Item from '../Item';
import Items from '../Items';
import Dropdown from '../../settings/Dropdown';
import { uninstall, urlParser } from 'modules/helpers/marketplace';
export default class Added extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
constructor() {
super();
this.state = {
installed: JSON.parse(localStorage.getItem('installed')),
item: {
name: 'Name',
author: 'Author',
description: 'Description',
//updated: '???',
version: '1.0.0',
icon: ''
},
button: '',
display: {
marketplace: 'block',
item: 'none'
}
item: {},
button: ''
};
this.buttons = {
uninstall: <button className='removeFromMue' onClick={() => this.uninstall()}>{window.language.modals.main.marketplace.product.buttons.remove}</button>,
uninstall: <button className='removeFromMue' onClick={() => this.uninstall()}>{this.getMessage('modals.main.marketplace.product.buttons.remove')}</button>,
};
this.language = window.language.modals.main.addons;
}
toggle(type, data) {
@@ -44,36 +35,83 @@ export default class Added extends React.PureComponent {
name: data,
display_name: info.name,
author: info.author,
description: MarketplaceFunctions.urlParser(info.description.replace(/\n/g, '<br>')),
description: urlParser(info.description.replace(/\n/g, '<br>')),
//updated: info.updated,
version: info.version,
icon: info.screenshot_url
icon: info.screenshot_url,
quote_api: info.quote_api || null
},
button: this.buttons.uninstall,
display: {
marketplace: 'none',
item: 'block'
}
button: this.buttons.uninstall
});
variables.stats.postEvent('marketplace', 'Item viewed');
} else {
this.setState({
display: {
marketplace: 'block',
item: 'none'
}
item: {}
});
}
}
uninstall() {
MarketplaceFunctions.uninstall(this.state.item.type, this.state.item.display_name);
uninstall(this.state.item.type, this.state.item.display_name);
toast(window.language.toasts.uninstalled);
toast(this.getMessage('toasts.uninstalled'));
this.setState({
button: '',
installed: JSON.parse(localStorage.getItem('installed'))
});
variables.stats.postEvent('marketplace', 'Uninstall');
}
sortAddons(value, sendEvent) {
let installed = JSON.parse(localStorage.getItem('installed'));
switch (value) {
case 'newest':
installed.reverse();
break;
case 'oldest':
break;
case 'a-z':
installed.sort();
break;
case 'z-a':
installed.sort();
installed.reverse();
break;
default:
break;
}
this.setState({
installed: installed
});
if (sendEvent) {
variables.stats.postEvent('marketplace', 'Sort');
}
}
updateCheck() {
let updates = 0;
this.state.installed.forEach(async (item) => {
const data = await (await fetch(variables.constants.MARKETPLACE_URL + '/item/' + item.name)).json();
if (data.version !== item.version) {
updates++;
}
});
if (updates > 0) {
toast(this.getMessage('modals.main.addons.updates_available', {
amount: updates
}));
} else {
toast(this.getMessage('modals.main.addons.no_updates'));
}
}
componentDidMount() {
this.sortAddons(localStorage.getItem('sortAddons'), false);
}
render() {
@@ -81,20 +119,29 @@ export default class Added extends React.PureComponent {
return (
<div className='emptyitems'>
<div className='emptyMessage'>
<LocalMallIcon/>
<h1>{this.language.empty.title}</h1>
<p className='description'>{this.language.empty.description}</p>
<LocalMall/>
<h1>{this.getMessage('modals.main.addons.empty.title')}</h1>
<p className='description'>{this.getMessage('modals.main.addons.empty.description')}</p>
</div>
</div>
);
}
if (this.state.item.display_name) {
return <Item data={this.state.item} button={this.state.button} toggleFunction={() => this.toggle()} />;
}
return (
<>
<div style={{ 'display': this.state.display.marketplace }}>
<Items items={this.state.installed} toggleFunction={(input) => this.toggle('item', input)} />
</div>
<Item data={this.state.item} button={this.state.button} toggleFunction={() => this.toggle()} display={this.state.display.item} />
<Dropdown label={this.getMessage('modals.main.addons.sort.title')} name='sortAddons' onChange={(value) => this.sortAddons(value)}>
<option value='newest'>{this.getMessage('modals.main.addons.sort.newest')}</option>
<option value='oldest'>{this.getMessage('modals.main.addons.sort.oldest')}</option>
<option value='a-z'>{this.getMessage('modals.main.addons.sort.a_z')}</option>
<option value='z-a'>{this.getMessage('modals.main.addons.sort.z_a')}</option>
</Dropdown>
<button className='addToMue sideload updateCheck' onClick={() => this.updateCheck()}>{this.getMessage('modals.main.addons.check_updates')}</button>
<br/>
<Items items={this.state.installed} toggleFunction={(input) => this.toggle('item', input)} />
</>
);
}

View File

@@ -0,0 +1,309 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import {
SettingsRounded as Settings,
PhotoOutlined as Photos,
FormatQuoteOutlined as Quotes
} from '@mui/icons-material';
import { TextField } from '@mui/material';
import { toast } from 'react-toastify';
import { saveFile } from 'modules/helpers/settings/modals';
import FileUpload from '../../settings/FileUpload';
import Dropdown from '../../settings/Dropdown';
import '../../../welcome/welcome.scss';
export default class Create extends PureComponent {
constructor() {
super();
this.state = {
currentTab: 1,
addonMetadata: {
name: '',
description: '',
type: '',
version: '',
author: '',
icon_url: '',
screenshot_url: ''
},
addonData: '',
settingsClasses: {
current: 'toggle lightTheme',
json: 'toggle lightTheme'
}
};
}
changeTab(tab, type) {
if (type) {
return this.setState({
currentTab: tab,
addonMetadata: {
type: type
}
});
}
this.setState({
currentTab: tab
});
}
importSettings(input) {
const data = input || localStorage;
let settings = {};
Object.keys(data).forEach((key) => {
if (key === 'statsData' || key === 'firstRun' || key === 'showWelcome' || key === 'language' || key === 'installed' || key === 'stats') {
return;
}
settings[key] = localStorage.getItem(key);
});
this.setState({
addonData: settings,
settingsClasses: {
current: input ? 'toggle lightTheme' : 'toggle lightTheme active',
json: input ? 'toggle lightTheme active' : 'toggle lightTheme'
}
});
toast(variables.language.getMessage(variables.languagecode, 'toasts.imported'));
}
updateQuotePackType(type) {
if (type === 'quotePack') {
this.setState({
addonMetadata: {
type,
name: this.state.addonMetadata.name,
description: this.state.addonMetadata.description,
version: this.state.addonMetadata.version,
author: this.state.addonMetadata.author,
icon_url: this.state.addonMetadata.icon_url,
screenshot_url: this.state.addonMetadata.screenshot_url,
quotes: []
}
});
} else {
this.setState({
addonMetadata: {
type,
name: this.state.addonMetadata.name,
description: this.state.addonMetadata.description,
version: this.state.addonMetadata.version,
author: this.state.addonMetadata.author,
icon_url: this.state.addonMetadata.icon_url,
screenshot_url: this.state.addonMetadata.screenshot_url
},
addonData: {
url: '',
name: '',
author: ''
}
});
}
}
updateQuotePackAPI(type, data) {
this.setState({
addonData: {
url: (type === 'url') ? data : this.state.addonData.url || '',
name: (type === 'name') ? data : this.state.addonData.name || '',
author: (type === 'author') ? data : this.state.addonData.author || '',
}
});
}
importQuotes() {
this.setState({
addonData: {
quotes: JSON.parse(localStorage.getItem('customQuote')) || []
}
});
toast(variables.language.getMessage(variables.languagecode, 'toasts.imported'));
}
importPhotos() {
let data = [];
try {
data = JSON.parse(localStorage.getItem('customBackground'));
toast(variables.language.getMessage(variables.languagecode, 'toasts.imported'));
} catch (e) {
console.log(e);
toast(variables.language.getMessage(variables.languagecode, 'toasts.error'));
}
this.setState({
addonData: {
photos: data
}
});
}
downloadAddon() {
saveFile({
name: this.state.addonMetadata.name,
description: this.state.addonMetadata.description,
type: (this.state.addonMetadata.type === 'quote_api') ? 'quotes' : this.state.addonMetadata.type,
version: this.state.addonMetadata.version,
author: this.state.addonMetadata.author,
icon_url: this.state.addonMetadata.icon_url,
screenshot_url: this.state.addonMetadata.screenshot_url,
[this.state.addonMetadata.type]: this.state.addonData
}, this.state.addonMetadata.name + '.json');
}
render() {
let tabContent;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
const chooseType = (
<>
<h3>{getMessage('modals.main.settings.sections.time.type')}</h3>
<div className='themesToggleArea'>
<div className='options'>
<div className='toggle lightTheme' onClick={() => this.changeTab(2, 'photos')}>
<Photos/>
<span>{getMessage('modals.main.marketplace.photo_packs')}</span>
</div>
<div className='toggle lightTheme' onClick={() => this.changeTab(2, 'quotes')}>
<Quotes/>
<span>{getMessage('modals.main.marketplace.quote_packs')}</span>
</div>
<div className='toggle lightTheme' onClick={() => this.changeTab(2, 'settings')}>
<Settings/>
<span>{getMessage('modals.main.marketplace.preset_settings')}</span>
</div>
</div>
</div>
</>
);
// todo: find a better way to do all this
const nextDescriptionDisabled = (this.state.addonMetadata.name !== undefined &&
this.state.addonMetadata.description !== undefined &&
this.state.addonMetadata.version !== undefined && this.state.addonMetadata.author !== undefined &&
this.state.addonMetadata.icon_url !== undefined && this.state.addonMetadata.screenshot_url !== undefined)
? false : true;
const setMetadata = (data, type) => {
this.setState({
addonMetadata: {
name: (type === 'name') ? data : this.state.addonMetadata.name,
description: (type === 'description') ? data : this.state.addonMetadata.description,
version: (type === 'version') ? data : this.state.addonMetadata.version,
author: (type === 'author') ? data : this.state.addonMetadata.author,
icon_url: (type === 'icon_url') ? data : this.state.addonMetadata.icon_url,
screenshot_url: (type === 'screenshot_url') ? data : this.state.addonMetadata.screenshot_url,
type: this.state.addonMetadata.type
}
});
};
const writeDescription = (
<>
<h3>{getMessage('modals.main.marketplace.product.information')}</h3>
<TextField label={getMessage('modals.main.addons.create.metadata.name')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonMetadata.name} onInput={(e) => setMetadata(e.target.value, 'name')}/>
<TextField label={getMessage('modals.main.marketplace.product.version')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonMetadata.version} onInput={(e) => setMetadata(e.target.value, 'version')}/>
<TextField label={getMessage('modals.main.marketplace.product.author')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonMetadata.author} onInput={(e) => setMetadata(e.target.value, 'author')}/>
<TextField label={getMessage('modals.main.addons.create.metadata.icon_url')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonMetadata.icon_url} onInput={(e) => setMetadata(e.target.value, 'icon_url')}/>
<TextField label={getMessage('modals.main.addons.create.metadata.screenshot_url')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonMetadata.screenshot_url} onInput={(e) => setMetadata(e.target.value, 'screenshot_url')}/>
<TextField label={getMessage('modals.main.addons.create.metadata.description')} varient='outlined' InputLabelProps={{ shrink: true }} multiline spellCheck={false} rows={4} InputLabelProps={{ shrink: true }} value={this.state.addonMetadata.description} onInput={(e) => setMetadata(e.target.value, 'description')}/>
<br/>
<button onClick={() => this.changeTab(1)} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.welcome.buttons.previous')}</button>
<button onClick={() => this.changeTab(this.state.addonMetadata.type)} className='uploadbg' disabled={nextDescriptionDisabled}>{getMessage('modals.welcome.buttons.next')}</button>
</>
);
// settings
const nextSettingsDisabled = (this.state.addonData === '') ? true : false;
const importSettings = (
<>
<h3>{getMessage('modals.mwelcome.sections.title')}</h3>
<div className='themesToggleArea'>
<div className='options'>
<div className={this.state.settingsClasses.current} onClick={() => this.importSettings()}>
<span>{getMessage('modals.main.addons.create.settings.current')}</span>
</div>
<div className={this.state.settingsClasses.json} onClick={() => document.getElementById('file-input').click()}>
<span>{getMessage('modals.main.addons.create.settings.json')}</span>
</div>
</div>
</div>
<FileUpload id='file-input' type='settings' accept='application/json' loadFunction={(e) => this.importSettings(JSON.parse(e.target.result))} />
<br/><br/>
<button onClick={() => this.changeTab(2)} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.welcome.buttons.previous')}</button>
<button onClick={() => this.changeTab(3)} className='uploadbg' disabled={nextSettingsDisabled}>{getMessage('modals.welcome.buttons.next')}</button>
</>
);
// quotes
const nextQuotesDisabled = ((this.state.addonMetadata.type === 'quote_api' && this.state.addonData.url !== '' && this.state.addonData.name !== '' && this.state.addonData.author !== '')
|| (this.state.addonMetadata.type === 'quotes' && this.state.addonData.quotes !== '')) ? false : true;
const addQuotes = (
<>
<h3>{getMessage('modals.main.addons.create.quotes.title')}</h3>
<Dropdown label={getMessage('modals.main.settings.sections.time.type')} noSetting onChange={(e) => this.updateQuotePackType(e)}>
<option value='quotes'>{getMessage('modals.main.addons.create.quotes.local.title')}</option>
<option value='quote_api'>{getMessage('modals.main.addons.create.quotes.api.title')}</option>
</Dropdown>
{this.state.addonMetadata.type === 'quote_api' ? <>
<h3>{getMessage('modals.main.addons.create.quotes.api.title')}</h3>
<TextField label={getMessage('modals.main.addons.create.quotes.api.url')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonData.url} onInput={(e) => this.updateQuotePack(e.target.value, 'url')}/>
<TextField label={getMessage('modals.main.addons.create.quotes.api.name')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonData.name} onInput={(e) => this.updateQuotePack(e.target.value, 'name')}/>
<TextField label={getMessage('modals.main.addons.create.quotes.api.author')} varient='outlined' InputLabelProps={{ shrink: true }} value={this.state.addonData.author} onInput={(e) => this.updateQuotePack(e.target.value, 'author')}/>
<br/><br/>
</> : <>
<h3>{getMessage('modals.main.addons.create.quotes.local.title')}</h3>
<button onClick={() => this.importQuotes()} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.main.addons.create.settings.current')}</button>
<br/><br/>
</>}
<button onClick={() => this.changeTab(2)} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.welcome.buttons.previous')}</button>
<button onClick={() => this.changeTab(3)} className='uploadbg' disabled={nextQuotesDisabled}>{getMessage('modals.welcome.buttons.next')}</button>
</>
);
// photos
const nextPhotosDisabled = (this.state.addonData.photos !== '' && this.state.addonData.photos !== []) ? false : true;
const addPhotos = (
<>
<h3>{getMessage('modals.main.addons.create.photos.title')}</h3>
<h3>{getMessage('modals.main.addons.create.quotes.local.title')}</h3>
<button onClick={() => this.importPhotos()} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.main.addons.create.settings.current')}</button>
<br/><br/>
<button onClick={() => this.changeTab(2)} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.welcome.buttons.previous')}</button>
<button onClick={() => this.changeTab(3)} className='uploadbg' disabled={nextPhotosDisabled}>{getMessage('modals.welcome.buttons.next')}</button>
</>
);
const downloadAddon = (
<>
<h3>{getMessage('modals.main.addons.create.finish.title')}</h3>
<button onClick={() => this.downloadAddon()} className='upload'>{getMessage('modals.main.addons.create.finish.download')}</button>
<br/><br/>
<button onClick={() => this.changeTab((this.state.addonMetadata.type === 'quote_api') ? 'quotes' : this.state.addonMetadata.type)} className='uploadbg' style={{ marginRight: '10px' }}>{getMessage('modals.welcome.buttons.previous')}</button>
</>
);
switch (this.state.currentTab) {
case 2: tabContent = writeDescription; break;
case 'settings': tabContent = importSettings; break;
case 'quotes': tabContent = addQuotes; break;
case 'photos': tabContent = addPhotos; break;
case 3: tabContent = downloadAddon; break;
default: tabContent = chooseType;
}
return (
<>
<h2>{getMessage('modals.main.addons.create.other_title')}</h2>
{tabContent}
</>
);
}
}

View File

@@ -1,16 +1,17 @@
import React from 'react';
import WifiOffIcon from '@material-ui/icons/WifiOff';
import LocalMallIcon from '@material-ui/icons/LocalMall';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { WifiOff, LocalMall } from '@mui/icons-material';
import Item from '../Item';
import Items from '../Items';
import Dropdown from '../../settings/Dropdown';
import MarketplaceFunctions from '../../../../../modules/helpers/marketplace';
import { install, urlParser, uninstall } from 'modules/helpers/marketplace';
import { toast } from 'react-toastify';
export default class Marketplace extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
export default class Marketplace extends React.PureComponent {
constructor() {
super();
this.state = {
@@ -18,24 +19,12 @@ export default class Marketplace extends React.PureComponent {
button: '',
featured: {},
done: false,
item: {
name: 'Name',
author: 'Author',
description: 'Description',
//updated: '???',
version: '1.0.0',
icon: ''
},
display: {
marketplace: 'block',
item: 'none'
}
item: {}
};
this.buttons = {
uninstall: <button className='removeFromMue' onClick={() => this.manage('uninstall')}>{window.language.modals.main.marketplace.product.buttons.remove}</button>,
install: <button className='addToMue' onClick={() => this.manage('install')}>{window.language.modals.main.marketplace.product.buttons.addtomue}</button>
uninstall: <button className='removeFromMue' onClick={() => this.manage('uninstall')}>{this.getMessage('modals.main.marketplace.product.buttons.remove')}</button>,
install: <button className='addToMue' onClick={() => this.manage('install')}>{this.getMessage('modals.main.marketplace.product.buttons.addtomue')}</button>
};
this.language = window.language.modals.main.marketplace;
this.controller = new AbortController();
}
@@ -44,10 +33,10 @@ export default class Marketplace extends React.PureComponent {
let info;
// get item info
try {
info = await (await fetch(`${window.constants.MARKETPLACE_URL}/item/${this.props.type}/${data}`, { signal: this.controller.signal })).json();
info = await (await fetch(`${variables.constants.MARKETPLACE_URL}/item/${this.props.type}/${data}`, { signal: this.controller.signal })).json();
} catch (e) {
if (this.controller.signal.aborted === false) {
return toast(window.language.toasts.error);
return toast(this.getMessage('toasts.error'));
}
}
@@ -57,66 +46,106 @@ export default class Marketplace extends React.PureComponent {
// check if already installed
let button = this.buttons.install;
let addonInstalled = false;
let addonInstalledVersion;
const installed = JSON.parse(localStorage.getItem('installed'));
if (installed.some((item) => item.name === info.data.name)) {
button = this.buttons.uninstall;
addonInstalled = true;
for (let i = 0; i < installed.length; i++) {
if (installed[i].name === info.data.name) {
addonInstalledVersion = installed[i].version;
break;
}
}
}
this.setState({
item: {
type: this.props.type,
type: info.data.type,
display_name: info.data.name,
author: info.data.author,
description: MarketplaceFunctions.urlParser(info.data.description.replace(/\n/g, '<br>')),
description: urlParser(info.data.description.replace(/\n/g, '<br>')),
//updated: info.updated,
version: info.data.version,
icon: info.data.screenshot_url,
data: info.data
data: info.data,
addonInstalled,
addonInstalledVersion
},
button: button,
display: {
item: 'block',
marketplace: 'none'
}
button: button
});
variables.stats.postEvent('marketplace-item', `${this.state.item.display_name} viewed`);
} else {
this.setState({
display: {
marketplace: 'block',
item: 'none'
}
item: {}
});
}
}
async getItems() {
const { data } = await (await fetch(window.constants.MARKETPLACE_URL + '/all', { signal: this.controller.signal })).json();
const featured = await (await fetch(window.constants.MARKETPLACE_URL + '/featured', { signal: this.controller.signal })).json();
const { data } = await (await fetch(variables.constants.MARKETPLACE_URL + '/items/' + this.props.type, { signal: this.controller.signal })).json();
const featured = await (await fetch(variables.constants.MARKETPLACE_URL + '/featured', { signal: this.controller.signal })).json();
if (this.controller.signal.aborted === true) {
return;
}
this.setState({
items: data[this.props.type],
items: data,
oldItems: data,
featured: featured.data,
done: true
});
this.sortMarketplace(localStorage.getItem('sortMarketplace'), false);
}
manage(type) {
if (type === 'install') {
MarketplaceFunctions.install(this.state.item.type, this.state.item.data);
install(this.state.item.type, this.state.item.data);
} else {
MarketplaceFunctions.uninstall(this.state.item.type, this.state.item.display_name);
uninstall(this.state.item.type, this.state.item.display_name);
}
toast(window.language.toasts[type + 'ed']);
toast(this.getMessage('toasts.' + type + 'ed'));
this.setState({
button: (type === 'install') ? this.buttons.uninstall : this.buttons.install
});
variables.stats.postEvent('marketplace-item', `${this.state.item.display_name} ${(type === 'install' ? 'installed': 'uninstalled')}`);
variables.stats.postEvent('marketplace', (type === 'install' ? 'Install': 'Uninstall'));
}
sortMarketplace(value, sendEvent) {
let items = this.state.oldItems;
switch (value) {
case 'a-z':
items.sort();
// fix sort not working sometimes
if (this.state.sortType === 'z-a') {
items.reverse();
}
break;
case 'z-a':
items.sort();
items.reverse();
break;
default:
break;
}
this.setState({
items: items,
sortType: value
});
if (sendEvent) {
variables.stats.postEvent('marketplace', 'Sort');
}
}
componentDidMount() {
@@ -145,35 +174,57 @@ export default class Marketplace extends React.PureComponent {
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
return errorMessage(<>
<WifiOffIcon/>
<h1>{this.language.offline.title}</h1>
<p className='description'>{this.language.offline.description}</p>
<WifiOff/>
<h1>{this.getMessage('modals.main.marketplace.offline.title')}</h1>
<p className='description'>{this.getMessage('modals.main.marketplace.offline.description')}</p>
</>);
}
if (this.state.done === false) {
return errorMessage(<h1>{window.language.modals.main.loading}</h1>);
return errorMessage(<h1>{this.getMessage('modals.main.loading')}</h1>);
}
const featured = () => {
const openFeatured = () => {
variables.stats.postEvent('marketplace', 'Featured clicked');
window.open(this.state.featured.buttonLink);
};
return (
<div className='featured' style={{ backgroundColor: this.state.featured.colour }}>
<p>{this.state.featured.title}</p>
<h1>{this.state.featured.name}</h1>
<button className='addToMue' onClick={() => openFeatured()}>{this.state.featured.buttonText}</button>
</div>
);
}
if (this.state.items.length === 0) {
return errorMessage(<>
<LocalMallIcon/>
<h1>{window.language.modals.main.addons.empty.title}</h1>
<p className='description'>{this.language.no_items}</p>
</>);
return (
<>
{featured()}
{errorMessage(<>
<LocalMall/>
<h1>{this.getMessage('modals.main.addons.empty.title')}</h1>
<p className='description'>{this.getMessage('modals.main.marketplace.no_items')}</p>
</>)}
</>
);
}
if (this.state.item.display_name) {
return <Item data={this.state.item} button={this.state.button} toggleFunction={() => this.toggle()} addonInstalled={this.state.item.addonInstalled} addonInstalledVersion={this.state.item.addonInstalledVersion}/>;
}
return (
<>
<div style={{ 'display': this.state.display.marketplace }}>
<div className='featured' style={{ 'backgroundColor': this.state.featured.colour }}>
<p>{this.state.featured.title}</p>
<h1>{this.state.featured.name}</h1>
<button className='addToMue' onClick={() => window.open(this.state.featured.buttonLink)}>{this.state.featured.buttonText}</button>
</div>
<Items items={this.state.items} toggleFunction={(input) => this.toggle('item', input)} />
</div>
<Item data={this.state.item} button={this.state.button} toggleFunction={() => this.toggle()} display={this.state.display.item} />
{featured()}
<br/>
<Dropdown label={this.getMessage('modals.main.addons.sort.title')} name='sortMarketplace' onChange={(value) => this.sortMarketplace(value)}>
<option value='a-z'>{this.getMessage('modals.main.addons.sort.a_z')}</option>
<option value='z-a'>{this.getMessage('modals.main.addons.sort.z_a')}</option>
</Dropdown>
<Items items={this.state.items} toggleFunction={(input) => this.toggle('item', input)} />
</>
);
}

View File

@@ -1,27 +1,67 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { LocalMall } from '@mui/icons-material';
import { toast } from 'react-toastify';
import Modal from 'react-modal';
import LocalMallIcon from '@material-ui/icons/LocalMall';
import SideloadFailedModal from '../SideloadFailedModal';
import FileUpload from '../../settings/FileUpload';
import MarketplaceFunctions from '../../../../../modules/helpers/marketplace';
import { install } from 'modules/helpers/marketplace';
import { toast } from 'react-toastify';
export default class Sideload extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
export default function Sideload() {
const install = (input) => {
MarketplaceFunctions.install(input.type, input);
toast(window.language.toasts.installed);
};
constructor(props) {
super(props);
this.state = {
showFailed: false,
failedReason: ''
}
}
return (
<div className='emptyitems'>
<div className='emptyMessage'>
<FileUpload id='file-input' type='settings' accept='application/json' loadFunction={(e) => install(JSON.parse(e.target.result))} />
<LocalMallIcon/>
<h1>{window.language.modals.main.addons.sideload}</h1>
<button className='addToMue sideload' onClick={() => document.getElementById('file-input').click()}>{window.language.modals.main.settings.sections.background.source.upload}</button>
installAddon(input) {
let failedReason = '';
if (!input.name) {
failedReason = this.getMessage('modals.main.addons.sideload.errors.no_name');
} else if (!input.author) {
failedReason = this.getMessage('modals.main.addons.sideload.errors.no_author');
} else if (!input.type) {
failedReason = this.getMessage('modals.main.addons.sideload.errors.no_type');
} else if (!input.version) {
failedReason = this.getMessage('modals.main.addons.sideload.errors.no_version');
} else if (input.type === 'photos' && (!input.photos || !input.photos.length || !input.photos[0].url.default || !input.photos[0].photographer || !input.photos[0].location)) {
failedReason = this.getMessage('modals.main.addons.sideload.errors.invalid_photos');
} else if (input.type === 'quotes' && (!input.quotes || !input.quotes.length || !input.quotes[0].quote || !input.quotes[0].author)) {
failedReason = this.getMessage('modals.main.addons.sideload.errors.invalid_quotes');
}
if (failedReason !== '') {
return this.setState({
failedReason,
showFailed: true
});
}
install(input.type, input);
toast(this.getMessage('toasts.installed'));
variables.stats.postEvent('marketplace', 'Sideload');
}
render() {
return (
<div className='emptyitems'>
<div className='emptyMessage'>
<FileUpload id='file-input' type='settings' accept='application/json' loadFunction={(e) => this.installAddon(JSON.parse(e.target.result))} />
<LocalMall/>
<h1>{this.getMessage('modals.main.addons.sideload.title')}</h1>
<button className='addToMue sideload' onClick={() => document.getElementById('file-input').click()}>{this.getMessage('modals.main.settings.sections.background.source.upload')}</button>
</div>
<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ showFailed: false })} isOpen={this.state.showFailed} className='Modal resetmodal mainModal sideloadModal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<SideloadFailedModal modalClose={() => this.setState({ showFailed: false })} reason={this.state.failedReason}/>
</Modal>
</div>
</div>
);
);
}
}

View File

@@ -1,12 +1,15 @@
@import '../../../../scss/variables';
@import 'modules/sidebar';
@import 'modules/navbar';
@import 'modules/tab-content';
@import 'modules/links';
@import 'modules/scrollbars';
@import 'settings/main';
@import 'settings/buttons';
@import 'settings/dropdown';
@import 'settings/daypicker';
@import 'marketplace/main';
@import 'marketplace/buttons';
.Modal {
color: var(--modal-text);
@@ -15,7 +18,6 @@
border: none;
opacity: 1;
z-index: -2;
padding: 25px;
transition-timing-function: ease-in;
border-radius: map-get($modal, 'border-radius');
user-select: none;
@@ -28,16 +30,6 @@
}
}
.modalLink {
color: var(--modal-link);
cursor: pointer;
padding-left: 10px;
&:hover {
opacity: 0.8;
}
}
.closeModal {
position: absolute;
top: 1rem;
@@ -70,18 +62,15 @@
}
.ReactModal__Content {
min-height: calc(100vh - 30vh);
max-height: calc(100vh - 10vh);
box-shadow: 0 0 30px 0 rgba(0, 0, 0, 0.25);
overflow-y: auto;
position: relative;
// animation
opacity: 0;
transform: scale(0);
transition: all 300ms cubic-bezier(0.47, 1.64, 0.41, 0.8);
}
/* modal transition */
.ReactModal__Content--after-open {
opacity: 1;
transform: scale(1);
@@ -99,49 +88,9 @@
}
}
@media only screen and (min-height: 700px) {
.ReactModal__Content {
min-height: 600px;
}
}
ul.sidebar {
position: absolute;
top: 0;
left: 0;
margin: 0;
padding-left: 0;
background: var(--sidebar);
border-radius: 12px 0 0 12px;
text-align: left;
font-size: 24px;
min-height: 100vh;
h1 {
text-align: center;
font-size: 1.8em;
}
svg {
vertical-align: middle;
padding: 5px;
}
hr {
height: 3px;
background: rgba(196, 196, 196, 0.74);
width: 75%;
outline: none;
border: none;
}
}
li {
list-style: none;
font-size: 24px;
padding: 5px 30px 5px 30px;
cursor: pointer;
margin-top: 2px;
/* main modal */
.mainModal {
padding: 25px;
}
#modal {
@@ -152,227 +101,25 @@ li {
bottom: 0;
left: 0;
height: 80%;
width: 60%;
}
@media only screen and (max-width: 1300px) {
@media (max-width: 1700px) {
#modal {
width: 90% !important;
width: 80% !important;
}
}
@media only screen and (min-width: 1310px) {
#modal {
width: 60%;
}
}
.tab-list-active {
background: var(--tab-active);
}
@media only screen and (max-width: 1200px) {
li.tab-list-item {
span {
display: none;
}
}
ul.sidebar {
h1 {
display: none;
}
}
}
.tab-list-item {
&:hover {
background: var(--tab-active);
}
}
.tab-content {
position: absolute;
h3 {
text-transform: uppercase;
}
}
@media only screen and (min-width: 2300px) {
.tab-content {
left: 350px;
top: 7%;
}
}
@media only screen and (max-width: 1920px) {
.tab-content {
left: 120px;
top: 50px;
}
}
@media only screen and (min-width: 1920px) {
.tab-content {
left: 350px;
top: 7%;
}
}
@media only screen and (max-width: 1400px), (min-width: 1400px) {
.tab-content {
left: 350px;
top: 75px;
}
}
@media only screen and (max-width: 1200px) {
.tab-content {
left: 125px;
top: 75px;
}
}
.navbar-item {
font-size: 22px;
font-weight: 500;
display: inline-flex;
&:hover {
color: rgb(165, 165, 165);
background: none;
}
span,
svg {
font-size: 1.1em !important;
}
svg {
font-size: 1.2em !important;
}
}
.modalNavbar {
position: absolute;
left: 20rem;
top: 1rem;
justify-content: center;
svg {
margin-right: 0.5rem;
padding: 3px;
font-size: 1.4em !important;
}
}
@media only screen and (max-width: 1200px) {
.modalNavbar {
left: 6rem;
}
}
@media only screen and (max-width: 1650px) {
li.navbar-item {
span {
display: none;
}
}
}
@media only screen and (min-width: 1200px) {
ul.sidebar {
width: 310px;
align-items: center;
}
}
.navbar-item-active {
background: map-get($theme-colours, 'gradient');
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
svg {
color: orange;
}
&:hover {
background: map-get($theme-colours, 'gradient');
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
}
::-webkit-scrollbar {
width: 6px;
border-top-right-radius: map-get($modal, 'border-radius');
border-bottom-right-radius: map-get($modal, 'border-radius');
}
::-webkit-scrollbar-thumb {
background: #636e72;
border-top-right-radius: map-get($modal, 'border-radius');
border-bottom-right-radius: map-get($modal, 'border-radius');
}
.abouticon {
width: 96px;
height: auto;
border-radius: 50%;
padding-right: 5px;
}
.resetmodal {
min-height: 300px !important;
max-width: 300px !important;
margin: auto;
h4 {
cursor: initial;
font-size: 1.1rem;
}
}
.resetfooter {
position: absolute;
bottom: 20px;
button.reset {
margin-right: 43px;
}
}
.resetoverlay {
background-color: rgba(0, 0, 0, 0.5);
}
.aboutIcon {
color: var(--modal-text) !important;
padding-right: 10px;
&:hover {
opacity: 0.8;
}
}
.aboutLink {
&:hover {
opacity: 0.8;
}
}
.MuiFormControl-root {
margin-top: 10px !important;
}
label, p, span.modalLink {
/* fixes for font size on extension */
label,
p,
span.modalLink {
font-size: 1rem;
}
h2 {
font-size: 1.5rem;
font-size: 2rem;
margin-bottom: 0;
}
h3 {
@@ -382,3 +129,13 @@ h3 {
h5 {
font-size: 0.8rem;
}
.tab-content {
hr {
height: 5px;
background: rgba(196, 196, 196, 0.74);
outline: none;
border: none;
margin: 50px 0 30px 0;
}
}

View File

@@ -1,22 +1,11 @@
#item a {
color: var(--modal-link);
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
.emptyitems {
width: 25vw;
display: flex;
justify-content: center;
margin-top: 90px;
}
@import 'modules/item';
@import 'modules/buttons';
@import 'modules/featured';
@import 'modules/lightbox';
.items {
display: inline-grid;
grid-template-columns: repeat(6, 1fr);
grid-template-columns: repeat(4, 1fr);
margin-top: 15px;
.item {
@@ -25,11 +14,9 @@
height: 80px;
width: 260px;
background: var(--sidebar);
transition: 0.5s;
cursor: pointer;
margin-right: 20px;
margin-top: 20px;
box-shadow: 0 0 6px rgb(0 0 0 / 30%);
img {
height: 80px;
@@ -66,48 +53,34 @@
}
&:hover {
transform: scale(1.1);
background: var(--tab-active);
}
}
}
@media only screen and (max-width: 2100px) {
@media (max-width: 1920px) {
.items {
grid-template-columns: repeat(3, 1fr);
}
}
@media only screen and (max-width: 1870px) {
@media (max-width: 1680px) and (min-width: 1500px) {
.items {
grid-template-columns: repeat(2, 1fr);
}
}
@media only screen and (min-width: 1079px), (max-width: 1869px) {
@media (max-width: 1440px) {
.items {
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(1, 1fr);
}
}
p.author {
margin-top: -5px;
}
#item {
h1 {
font-size: 40px;
line-height: 20px;
}
}
#item>h1,
#item>.MuiSvgIcon-root {
display: inline;
}
p.description {
margin-top: 0px;
max-width: 400px;
.emptyitems {
width: 25vw;
display: flex;
justify-content: center;
margin-top: 90px;
}
.emptyMessage {
@@ -119,91 +92,32 @@ p.description {
position: absolute;
width: 300px;
h1 {
font-size: 2rem;
}
svg {
font-size: 50px;
margin-bottom: -20px;
}
}
.backArrow {
cursor: pointer;
width: 2rem !important;
height: 2rem !important;
&:hover {
color: grey;
}
p.author {
margin-top: -5px;
}
.informationContainer {
margin-top: 20px;
}
.productInformation {
padding: 10px;
background: var(--sidebar);
width: 350px;
border-radius: 12px;
h4 {
cursor: initial !important;
}
li {
margin-left: -4px;
list-style: none;
font-size: 16px;
cursor: initial !important;
&.header {
text-transform: uppercase;
color: #787878;
margin-left: -5px;
}
}
}
#item>img, .updateimage, .updatechangelog>p>img {
#item>img,
.updateimage,
.updatechangelog>p>img {
border-radius: 12px;
height: 200px;
width: auto;
cursor: pointer;
}
.featured {
margin-top: 40px;
border-radius: 15px;
padding: 50px;
color: #fff;
box-shadow: 0 0 10px rgb(0 0 0 / 30%);
width: 85%;
button {
float: left;
margin-top: -7px;
border: 2px solid map-get($theme-colours, 'main');
color: map-get($theme-colours, 'main');
&:hover {
background: map-get($theme-colours, 'main');
color: #2d3436;
}
}
h1 {
margin-top: -20px;
}
}
.lightboxmodal {
margin: auto;
max-width: 60%;
img {
max-height: 80%;
max-width: 80%;
display: block;
margin-left: auto;
margin-right: auto;
}
/* sideload failed modal */
.sideloadModal {
min-width: 250px;
max-width: 250px;
overflow-x: hidden;
}

View File

@@ -29,7 +29,8 @@
border: 2px solid #ff4757;
color: #ff4757;
margin-top: 5px;
float: right;
margin-top: -10px;
&:hover {
background: #ff4757;
@@ -39,10 +40,28 @@
.addToMue {
@extend %storebutton;
margin-top: 12px;
float: right;
margin-top: -10px;
}
.sideload {
display: inline;
margin-top: 0px;
float: none !important;
}
button.round {
margin-left: 5px;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
line-height: 3px;
vertical-align: middle;
padding: 10px;
}
.updateCheck {
margin-top: 15px;
}

View File

@@ -0,0 +1,25 @@
.featured {
margin-top: 40px;
border-radius: 15px;
padding: 50px;
color: #fff;
box-shadow: 0 0 10px rgb(0 0 0 / 30%);
width: 85%;
button {
float: left;
margin-top: -7px;
border: 2px solid map-get($theme-colours, 'main');
color: map-get($theme-colours, 'main');
&:hover {
background: map-get($theme-colours, 'main');
color: #2d3436;
}
}
h1 {
margin-top: -20px;
font-size: 2rem;
}
}

View File

@@ -0,0 +1,77 @@
#item {
h1 {
font-size: 40px;
line-height: 20px;
}
img {
float: left;
}
a {
color: var(--modal-link);
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
}
.side {
float: right;
margin-left: 20px;
}
#item>h1,
#item>.MuiSvgIcon-root {
display: inline;
}
p.description {
margin-top: 0px;
max-width: 800px;
}
.backArrow {
cursor: pointer;
width: 2rem !important;
height: 2rem !important;
&:hover {
color: grey;
}
}
.informationContainer {
margin-top: 150px;
position: absolute;
}
.productInformation {
padding: 10px;
background: var(--sidebar);
width: 350px;
border-radius: 12px;
h4 {
cursor: initial !important;
}
li {
margin-left: -4px;
list-style: none;
font-size: 16px;
cursor: initial !important;
&.header {
text-transform: uppercase;
color: #787878;
margin-left: -5px;
}
}
}
.overview {
font-size: 30px !important;
}

View File

@@ -0,0 +1,16 @@
.lightboxmodal {
margin: auto;
max-width: 60%;
background: none !important;
box-shadow: none !important;
img {
height: auto;
width: 100%;
}
.closeModal {
color: #fff;
text-shadow: 0 0 20px rgb(0 0 0 / 30%);
}
}

View File

@@ -0,0 +1,25 @@
.resetLink {
color: var(--modal-link);
cursor: pointer;
&:hover {
opacity: 0.8;
}
span {
font-size: 1.2rem;
color: var(--modal-link);
vertical-align: text-bottom;
margin-left: 5px;
}
}
.modalLink {
color: var(--modal-link);
cursor: pointer;
margin-left: 5px;
&:hover {
opacity: 0.8;
}
}

View File

@@ -0,0 +1,72 @@
.navbar-item {
font-size: 22px;
font-weight: 500;
display: flex;
flex-direction: column;
align-items: center;
color: var(--photo-info);
&:hover {
svg {
background: var(--tab-active);
}
color: var(--modal-text)
}
span,
svg {
font-size: 1.1em !important;
}
svg {
font-size: 1.2em !important;
width: 60px;
padding: 5px;
border-radius: 20px;
color: var(--photo-info);
}
}
/* safari fix */
@supports (-webkit-hyphens: none) {
.navbar-item {
display: inline-block !important;
}
}
.modalNavbar {
position: absolute;
left: 20rem;
top: 1rem;
justify-content: center;
display: flex;
svg {
margin-right: 0.5rem;
padding: 3px;
vertical-align: middle;
}
}
@media only screen and (max-width: 1200px) {
.modalNavbar {
left: 6rem;
}
}
@media only screen and (max-width: 800px) {
li.navbar-item {
span {
display: none;
}
}
}
.navbar-item-active {
color: var(--modal-text);
svg {
background: var(--sidebar);
}
}

View File

@@ -0,0 +1,12 @@
::-webkit-scrollbar {
width: 6px;
height: 6px;
border-top-right-radius: map-get($modal, 'border-radius');
border-bottom-right-radius: map-get($modal, 'border-radius');
}
::-webkit-scrollbar-thumb {
background: #636e72;
border-top-right-radius: map-get($modal, 'border-radius');
border-bottom-right-radius: map-get($modal, 'border-radius');
}

View File

@@ -0,0 +1,87 @@
ul.sidebar {
position: absolute;
top: 0;
left: 0;
margin: 0;
padding-left: 0;
background: var(--sidebar);
border-radius: 12px 0 0 12px;
text-align: left;
font-size: 24px;
min-height: 110vh;
h1 {
text-align: center;
font-size: 1.8em;
}
svg {
vertical-align: middle;
padding: 5px;
}
hr {
height: 3px;
background: rgba(196, 196, 196, 0.74);
width: 75%;
outline: none;
border: none;
}
}
@media (max-height: 999px) and (min-height: 920px) {
ul.sidebar {
min-height: 160vh;
}
}
@media (max-height: 919px) and (min-height: 700px) {
ul.sidebar {
min-height: 200vh;
}
}
@media (max-height: 699px) and (min-height: 400px) {
ul.sidebar {
min-height: 260vh;
}
}
@media only screen and (min-width: 1200px) {
ul.sidebar {
width: 310px;
align-items: center;
}
}
li {
list-style: none;
font-size: 24px;
padding: 5px 30px 5px 30px;
cursor: pointer;
margin-top: 2px;
}
.tab-list-active {
background: var(--tab-active);
}
@media only screen and (max-width: 1200px) {
li.tab-list-item {
span {
display: none;
}
}
ul.sidebar {
h1 {
display: none;
}
}
}
.tab-list-item {
&:hover {
background: var(--tab-active);
}
}

View File

@@ -0,0 +1,43 @@
.tab-content {
position: absolute;
h3 {
font-size: 1.5rem;
margin-bottom: 0;
}
}
@media only screen and (min-width: 2300px) {
.tab-content {
left: 350px;
top: 7%;
}
}
@media only screen and (max-width: 1920px) {
.tab-content {
left: 120px;
top: 60px;
}
}
@media only screen and (min-width: 1920px) {
.tab-content {
left: 350px;
top: 9%;
}
}
@media only screen and (max-width: 1400px),
(min-width: 1400px) {
.tab-content {
left: 350px;
}
}
@media only screen and (max-width: 1200px) {
.tab-content {
left: 125px;
top: 90px;
}
}

View File

@@ -15,7 +15,6 @@
.reset {
@extend %settingsButton;
margin-left: 5px;
background-color: map-get($button-colours, 'reset');
border: 2px solid map-get($button-colours, 'reset');
@@ -25,7 +24,8 @@
}
}
.add {
.add,
.close {
@extend %settingsButton;
background-color: map-get($button-colours, 'other');
@@ -38,30 +38,36 @@
}
.close {
@extend %settingsButton;
padding: 10px 50px 10px 50px;
background-color: map-get($button-colours, 'other');
border: 2px solid map-get($button-colours, 'other');
&:hover {
color: map-get($button-colours, 'other');
border: 2px solid map-get($button-colours, 'other');
}
}
.export,
.uploadbg,
.import {
@extend %settingsButton;
background-color: map-get($button-colours, 'other');
color: map-get($theme-colours, 'primary');
border: 2px solid map-get($button-colours, 'other');
width: 440px;
height: 60px;
background-color: var(--sidebar);
border: none;
outline: none;
color: var(--modal-text);
border-radius: 12px;
margin-right: 25px;
width: 220px;
cursor: pointer;
&:hover {
color: map-get($button-colours, 'other');
border: 2px solid map-get($button-colours, 'other');
background-color: var(--tab-active);
}
&:disabled {
cursor: not-allowed;
background: none;
border: 1px solid var(--tab-active);
&:hover {
background: none;
border: 1px solid var(--tab-active);
}
}
}
@@ -70,30 +76,39 @@
margin-left: 20px;
}
.MuiIconButton-label > svg.MuiSvgIcon-root {
color: var(--modal-text) !important;
.round-small {
height: 10px !important;
width: 10px !important;
}
.sortableitem {
background: var(--sidebar) !important;
padding: 10px 80px;
padding-left: 10px;
border-radius: 15px;
margin-bottom: 10px;
font-size: 1.325rem;
.data-buttons-row {
width: 350px;
display: flex;
flex-direction: row;
svg {
font-size: 1.3rem;
button {
background: var(--sidebar);
text-align: center;
border-radius: 20px;
padding: 20px;
border: 3px solid var(--tab-active);
height: 40px;
font-size: 1rem;
margin: 0 10px 10px 0;
display: flex;
flex-direction: column-reverse;
align-items: center;
color: var(--modal-text);
&:hover {
background: var(--tab-active);
cursor: pointer;
}
}
&:hover {
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.15);
transition: 0.3s;
}
z-index: 999 !important;
}
.MuiTouchRipple-root {
background: transparent;
.customvideoicon {
position: absolute;
margin-bottom: 45px;
font-size: 3em !important;
}

View File

@@ -1,26 +0,0 @@
.DayPickerInput,
.input-container {
input {
width: 200px;
color: var(--modal-text) !important;
background: var(--sidebar);
border: none;
padding: 10px 10px;
border-radius: 5px;
}
}
.DayPicker-Day--selected {
background-color: #ff4757 !important;
color: white;
}
.DayPicker-Months,
.DayPickerInput-Overlay {
background-color: var(--background) !important;
color: var(--modal-text) !important;
}
.DayPicker:not(.DayPicker--interactionDisabled) .DayPicker-Day:not(.DayPicker-Day--disabled):not(.DayPicker-Day--selected):not(.DayPicker-Day--outside):hover {
color: black !important;
}

View File

@@ -1,22 +0,0 @@
select {
margin-left: 10px;
width: 120px;
color: var(--modal-text);
background: var(--sidebar);
border: none;
padding: 10px 10px;
border-radius: 5px;
}
// firefox dropdown
@supports (-moz-appearance: none) {
select {
-moz-appearance: none !important;
background: url('data:image/gif;base64,R0lGODlhBgAGAKEDAFVVVX9/f9TU1CgmNyH5BAEKAAMALAAAAAAGAAYAAAIODA4hCDKWxlhNvmCnGwUAOw==') right center no-repeat, var(--sidebar) !important;
background-position: calc(100% - 15px) center !important;
}
option {
font: -moz-pull-down-menu !important;
}
}

View File

@@ -1,13 +1,13 @@
input {
&[type=text] {
width: 200px;
color: var(--modal-text);
background: var(--sidebar);
border: none;
padding: 10px 10px;
border-radius: 5px;
}
@import 'modules/resetmodal';
@import 'modules/material-ui';
@import 'modules/reminder';
@import 'modules/tabs/about';
@import 'modules/tabs/changelog';
@import 'modules/tabs/order';
input {
/* colour picker */
&[type=color] {
border-radius: 100%;
height: 30px;
@@ -17,17 +17,18 @@ input {
-webkit-appearance: none;
vertical-align: middle;
background: none;
&::-webkit-color-swatch-wrapper {
padding: 0;
}
&::-webkit-color-swatch {
border: none;
border-radius: 100%;
}
}
/* firefox fixes for colour picker (using "," didn't work) */
&[type=color]::-moz-color-swatch {
border-radius: 100%;
height: 30px;
@@ -37,173 +38,44 @@ input {
-moz-appearance: none;
vertical-align: middle;
background: none;
&::-moz-color-swatch-wrapper {
padding: 0;
}
&::-moz-color-swatch {
border: none;
border-radius: 100%;
}
}
/* date picker */
&[type=date] {
width: 280px;
color: var(--modal-text);
background: var(--background);
border: solid var(--modal-text) 1px;
padding: 15px 20px;
border-radius: 4px;
display: flex !important;
}
}
/* dark theme date picker fix */
.dark {
::-webkit-calendar-picker-indicator {
filter: invert(1);
}
}
h4 {
cursor: pointer;
}
ul {
padding-left: 0px;
margin: 0;
.keybind-table {
text-align: left;
>label {
vertical-align: middle;
th {
padding-right: 10px;
}
}
.range {
-webkit-appearance: none;
width: 200px;
height: 12px;
border-radius: 12px;
outline: none;
background: var(--sidebar);
box-shadow: 0 0 100px rgba(0, 0, 0, 0.3);
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 12px;
background: var(--modal-text);
cursor: pointer;
}
&::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 12px;
border: 0;
background: var(--modal-text);
cursor: pointer;
}
}
.newFeature {
color: #ff4757;
font-size: 12px;
}
.settingsTextarea {
font-family: Consolas !important;
padding: 15px;
border-radius: 15px;
background-color: var(--sidebar) !important;
border: none;
margin-left: 0;
width: 400px;
height: 200px;
max-width: 60%;
}
.MuiCheckbox-colorPrimary.Mui-checked,
.MuiSwitch-colorPrimary.Mui-checked,
.MuIconButton-colorPrimary.Mui-checked,
.MuiSwitch-thumb,
.MuiRadio-colorSecondary.Mui-checked,
.PrivateSwitchBase-input-4,
.MuiRadio-root,
.aboutLink,
legend {
color: var(--modal-text) !important;
}
.MuiFormControlLabel-labelPlacementStart {
margin-left: 0px !important;
}
.MuiSwitch-colorPrimary.Mui-checked+.MuiSwitch-track {
background: darkgray !important;
}
.reminder-info {
position: absolute;
bottom: 20px;
right: 20px;
padding: 15px;
color: var(--modal-text);
background: var(--sidebar);
max-width: 300px;
border-radius: 0.7em;
h1 {
font-size: 1em;
}
}
.radio-title {
text-transform: uppercase;
font-weight: bold;
font-size: 1.17rem;
}
.radio-title-small {
text-transform: uppercase;
font-weight: bold;
font-size: 1rem;
}
.sortableitem {
color: var(--modal-text) !important;
cursor: move;
}
.updatechangelog {
max-width: 75%;
li {
cursor: initial;
font-size: 1rem;
list-style-type:disc;
padding: 0;
margin-left: 20px;
}
a {
color: var(--modal-link);
&:hover {
opacity: 0.8;
}
}
}
.changelogtab {
h1 {
max-width: 85%;
}
img {
max-width: 95%;
}
}
.sliderText {
color: var(--modal-text);
background: none;
border: none;
border-radius: 0;
font-size: 1rem;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
}

View File

@@ -0,0 +1,103 @@
/* these are overrides for the material ui default styles */
.MuiCheckbox-colorPrimary.Mui-checked,
.MuiSwitch-colorPrimary.Mui-checked,
.MuIconButton-colorPrimary.Mui-checked,
.MuiSwitch-thumb,
.MuiRadio-colorSecondary.Mui-checked,
.PrivateSwitchBase-input-4,
.MuiRadio-root,
.aboutLink,
.MuiSlider-colorPrimary,
legend {
color: var(--modal-text) !important;
}
.MuiFormControlLabel-labelPlacementStart {
margin-left: 0px !important;
}
.MuiSwitch-colorPrimary.Mui-checked+.MuiSwitch-track {
background: darkgray !important;
}
.MuiIconButton-label>svg.MuiSvgIcon-root {
color: var(--modal-text) !important;
}
.MuiTouchRipple-root {
background: transparent;
}
.MuiFormControl-root {
margin-top: 10px !important;
}
.checkbox svg {
fill: var(--modal-text) !important;
}
.radio-title {
font-weight: bold;
font-size: 1.17rem;
}
.radio-title-small {
font-weight: bold;
font-size: 1rem;
}
.MuiSlider-root {
margin-bottom: 30px !important;
}
.MuiOutlinedInput-notchedOutline {
border-color: var(--modal-text) !important;
}
.MuiFormLabel-root-MuiInputLabel-root {
color: var(--modal-text) !important;
}
.MuiInputLabel-root,
.MuiSlider-markLabel,
.MuiInputLabel-root,
.MuiSelect-icon,
.MuiSelect-select,
.Mui-focused,
legend,
.MuiOutlinedInput-input {
color: var(--modal-text) !important;
}
.MuiMenu-list {
background-color: var(--background) !important;
color: var(--modal-text) !important;
}
.Mui-selected {
background-color: var(--tab-active) !important;
}
.MuiTextField-root,
.MuiFormControl-root,
.MuiSlider-root {
width: 300px !important;
display: flex !important;
}
.Mui-disabled {
color: #818181 !important;
cursor: not-allowed;
.checkbox svg {
fill: #818181 !important;
}
}
.MuiPaper-root {
background-color: var(--background) !important;
}
.MuiSlider-valueLabel {
background-color: var(--tab-active) !important;
}

View File

@@ -0,0 +1,14 @@
.reminder-info {
position: absolute;
bottom: 20px;
right: 20px;
padding: 15px;
color: var(--modal-text);
background: var(--sidebar);
max-width: 300px;
border-radius: 0.7em;
h1 {
font-size: 1rem;
}
}

View File

@@ -0,0 +1,27 @@
.resetmodal {
min-height: 300px !important;
max-width: 300px !important;
margin: auto;
font-size: 1rem;
h4 {
cursor: initial;
font-size: 1.1rem;
}
}
.resetfooter {
position: absolute;
bottom: 20px;
width: 300px;
justify-content: center;
display: flex;
button.reset {
margin-right: 43px;
}
}
.resetoverlay {
background-color: rgba(0, 0, 0, 0.5);
}

View File

@@ -0,0 +1,27 @@
.aboutIcon {
color: var(--modal-text) !important;
padding-right: 10px;
&:hover {
opacity: 0.8;
}
}
.aboutLink {
&:hover {
opacity: 0.8;
}
}
.aboutLogo {
height: 100px;
width: auto;
margin-left: -15px;
}
.abouticon {
width: 96px;
height: auto;
border-radius: 50%;
padding-right: 5px;
}

View File

@@ -0,0 +1,35 @@
.updatechangelog {
max-width: 75%;
li {
cursor: initial;
font-size: 1rem;
list-style-type: disc;
padding: 0;
margin-left: 20px;
}
a {
color: var(--modal-link);
&:hover {
opacity: 0.8;
}
}
}
.changelogtab {
h1 {
max-width: 85%;
font-size: 2rem;
margin-bottom: -10px !important;
}
h5 {
line-height: 0px !important;
}
img {
max-width: 95%;
}
}

View File

@@ -0,0 +1,54 @@
.sortableitem {
background: var(--sidebar) !important;
padding: 10px 80px;
padding-left: 10px;
border-radius: 15px;
margin-bottom: 10px;
font-size: 1.325rem;
color: var(--modal-text) !important;
cursor: move;
width: 150px;
z-index: 999 !important;
svg {
font-size: 1.3rem;
}
&:hover {
background: var(--tab-active) !important;
}
}
ul {
padding-left: 0px;
margin: 0;
>label {
vertical-align: middle;
}
}
.images-row {
display: flex;
flex-wrap: wrap;
width: 500px;
div {
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
background-color: var(--sidebar);
border: 20px solid var(--sidebar);
border-radius: 20px;
margin: 0 20px 20px 0;
display: flex;
align-items: flex-end;
justify-content: center;
svg {
font-size: 1.9em;
}
}
}

View File

@@ -31,3 +31,8 @@ div.color-preview-area > div > div:nth-child(5) {
.gradient-type-item.active::after {
border: 2px solid var(--modal-text) !important;
}
.text-input, .number-input {
background-color: var(--sidebar) !important;
color: var(--modal-text) !important;
}

View File

@@ -1,12 +1,10 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { Checkbox as CheckboxUI, FormControlLabel } from '@mui/material';
import EventBus from '../../../../modules/helpers/eventbus';
import SettingsFunctions from '../../../../modules/helpers/settings';
import EventBus from 'modules/helpers/eventbus';
import CheckboxUI from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
export default class Checkbox extends React.PureComponent {
export default class Checkbox extends PureComponent {
constructor(props) {
super(props);
this.state = {
@@ -15,12 +13,19 @@ export default class Checkbox extends React.PureComponent {
}
handleChange = () => {
SettingsFunctions.setItem(this.props.name);
const value = (this.state.checked === true) ? false : true;
localStorage.setItem(this.props.name, value);
this.setState({
checked: (this.state.checked === true) ? false : true
checked: value
});
if (this.props.onChange) {
this.props.onChange(value);
}
variables.stats.postEvent('setting', `${this.props.name} ${(this.state.checked === true) ? 'enabled' : 'disabled'}`);
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
document.querySelector('.reminder-info').style.display = 'block';
@@ -32,19 +37,11 @@ export default class Checkbox extends React.PureComponent {
}
render() {
let text = this.props.text;
if (this.props.newFeature) {
text = <>{this.props.text} <span className='newFeature'> NEW</span></>;
} else if (this.props.betaFeature) {
text = <>{this.props.text} <span className='newFeature'> BETA</span></>;
}
return (
<>
<FormControlLabel
control={<CheckboxUI name={this.props.name} color='primary' checked={this.state.checked} onChange={this.handleChange} />}
label={text}
control={<CheckboxUI name={this.props.name} color='primary' className='checkbox' checked={this.state.checked} onChange={this.handleChange} disabled={this.props.disabled || false} />}
label={this.props.text}
/>
<br/>
</>

View File

@@ -1,33 +1,35 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent, createRef } from 'react';
import { InputLabel, MenuItem, FormControl, Select } from '@mui/material';
import EventBus from '../../../../modules/helpers/eventbus';
import EventBus from 'modules/helpers/eventbus';
export default class Dropdown extends React.PureComponent {
export default class Dropdown extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || '',
value: localStorage.getItem(this.props.name) || this.props.children[0].props.value,
title: ''
};
}
getLabel() {
return this.props.label ? <label>{this.props.label}</label> : null;
this.dropdown = createRef();
}
onChange = (e) => {
const { value } = e.target;
if (value === window.language.modals.main.loading) {
if (value === variables.language.getMessage(variables.languagecode, 'modals.main.loading')) {
return;
}
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
this.setState({
value: value,
title: e.target[e.target.selectedIndex].text
value
});
localStorage.setItem(this.props.name, value);
if (!this.props.noSetting) {
localStorage.setItem(this.props.name, value);
}
if (this.props.onChange) {
this.props.onChange(value);
@@ -43,22 +45,19 @@ export default class Dropdown extends React.PureComponent {
EventBus.dispatch('refresh', this.props.category);
}
// todo: find a better way to do this
componentDidMount() {
const element = document.getElementById(this.props.name);
this.setState({
title: element[element.selectedIndex].text
});
}
render() {
const id = 'dropdown' + this.props.name;
const label = this.props.label || '';
return (
<>
{this.getLabel()}
<select id={this.props.name} value={this.state.value} onChange={this.onChange} style={{width: `${(8*this.state.title.length) + 50}px`}}>
{this.props.children}
</select>
</>
<FormControl fullWidth>
<InputLabel id={id}>{label}</InputLabel>
<Select labelId={id} id={this.props.name} value={this.state.value} label={label} onChange={this.onChange} ref={this.dropdown} key={id}>
{this.props.manual ? this.props.children : this.props.children.map((e, index) => {
return e ? <MenuItem key={index} value={e.props ? e.props.value : ''}>{e.props ? e.props.children : ''}</MenuItem> : null
})}
</Select>
</FormControl>
);
}
}

View File

@@ -1,8 +1,10 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
export default class FileUpload extends React.PureComponent {
export default class FileUpload extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
componentDidMount() {
document.getElementById(this.props.id).onchange = (e) => {
const reader = new FileReader();
@@ -13,7 +15,7 @@ export default class FileUpload extends React.PureComponent {
} else {
// background upload
if (file.size > 2000000) {
return toast(window.language.modals.main.file_upload_error);
return toast(this.getMessage('modals.main.file_upload_error'));
}
reader.readAsDataURL(file);

View File

@@ -0,0 +1,24 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Slider from './Slider';
import Switch from './Switch';
import { values } from 'modules/helpers/settings/modals';
export default class Header extends PureComponent {
render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<>
<h2>{this.props.title}</h2>
<Switch name={this.props.setting} text={getMessage('modals.main.settings.enabled')} category={this.props.category} element={this.props.element || null} />
{this.props.zoomSetting ?
<><Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.widget_zoom')} name={this.props.zoomSetting} min='10' max='400' default='100' display='%' marks={values('zoom')} category={this.props.zoomCategory || this.props.category}/></>
: <br/>}
</>
);
}
}

View File

@@ -0,0 +1,24 @@
import variables from 'modules/variables';
import { Cancel } from '@mui/icons-material';
import { TextField } from '@mui/material';
export default function KeybindInput(props) {
const value = props.state[props.setting];
const getButton = () => {
if (!value) {
return <button className='cleanButton' style={{ visibility: 'hidden' }} onClick={() => props.action('reset', props.setting)}><Cancel/></button>;;
} else if (value === variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.keybinds.recording')) {
return <button className='cleanButton' onClick={() => props.action('cancel', props.setting)}><Cancel/></button>;
} else {
return <button className='cleanButton' onClick={() => props.action('reset', props.setting)}><Cancel/></button>;
}
}
return (
<>
<TextField label={props.name} onClick={() => props.action('listen', props.setting)} value={value || variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.keybinds.click_to_record')} readOnly spellCheck={false} varient='outlined' InputLabelProps={{ shrink: true }} />
{getButton()}
</>
);
}

View File

@@ -1,14 +1,10 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { Radio as RadioUI, RadioGroup, FormControlLabel, FormControl, FormLabel } from '@mui/material';
import EventBus from '../../../../modules/helpers/eventbus';
import EventBus from 'modules/helpers/eventbus';
import RadioUI from '@material-ui/core/Radio';
import RadioGroup from '@material-ui/core/RadioGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';
export default class Radio extends React.PureComponent {
export default class Radio extends PureComponent {
constructor(props) {
super(props);
this.state = {
@@ -23,12 +19,25 @@ export default class Radio extends React.PureComponent {
return;
}
if (this.props.name === 'language') {
// old tab name
if (localStorage.getItem('tabName') === variables.language.getMessage(variables.languagecode, 'tabname')) {
localStorage.setItem('tabName', require(`translations/${value.replace('-', '_')}.json`).tabname);
}
}
localStorage.setItem(this.props.name, value);
this.setState({
value: value
value
});
if (this.props.onChange) {
this.props.onChange(value);
}
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
document.querySelector('.reminder-info').style.display = 'block';

View File

@@ -1,23 +1,27 @@
import React from 'react';
import SettingsFunctions from '../../../../modules/helpers/settings';
export default function ResetModal(props) {
const language = window.language.modals.main.settings.sections.advanced.reset_modal;
import variables from 'modules/variables';
import { Close, Delete } from '@mui/icons-material';
import { setDefaultSettings } from 'modules/helpers/settings';
export default function ResetModal({ modalClose }) {
const reset = () => {
SettingsFunctions.setDefaultSettings('reset');
variables.stats.postEvent('setting', 'Reset');
setDefaultSettings('reset');
window.location.reload();
}
};
return (
<>
<h3 style={{'textAlign': 'center'}}>{language.title}</h3>
<h4>{language.question}</h4>
<p>{language.information}</p>
<h1 style={{ textAlign: 'center' }}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.advanced.reset_modal.title')}</h1>
<span>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.advanced.reset_modal.question')}</span>
<br/><br/>
<span>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.advanced.reset_modal.information')}</span>
<div className='resetfooter'>
<button className='reset' style={{ 'marginLeft': '0' }} onClick={() => reset()}>{window.language.modals.main.settings.buttons.reset}</button>
<button className='import' style={{ 'marginLeft': '5px' }} onClick={props.modalClose}>{language.cancel}</button>
<button className='round reset' style={{ marginLeft: 0 }} onClick={() => reset()}>
<Delete/>
</button>
<button className='round add' style={{ marginLeft: '5px' }} onClick={modalClose}>
<Close/>
</button>
</div>
</>
);

View File

@@ -1,23 +1,21 @@
// todo: find a better method to do width of number input
import React from 'react';
import EventBus from '../../../../modules/helpers/eventbus';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { Slider } from '@mui/material';
export default class Slider extends React.PureComponent {
import EventBus from 'modules/helpers/eventbus';
export default class SliderComponent extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || '',
numberWidth: ((localStorage.getItem(this.props.name).length + 1) * ((this.props.toast === true) ? 7.75 : 7))
value: localStorage.getItem(this.props.name) || this.props.default
};
this.language = window.language.modals.main.settings;
this.widthCalculation = (this.props.toast === true) ? 7.75 : 7;
}
handleChange = (e, text) => {
let { value } = e.target;
value = Number(value);
if (text) {
if (value === '') {
@@ -26,42 +24,54 @@ export default class Slider extends React.PureComponent {
});
}
if (Number(value) > this.props.max) {
if (value > this.props.max) {
value = this.props.max;
}
if (Number(value) < this.props.min) {
if (value < this.props.min) {
value = this.props.min;
}
}
localStorage.setItem(this.props.name, value);
this.setState({
value: value,
numberWidth: ((value.length + 1) * this.widthCalculation)
value
});
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
document.querySelector('.reminder-info').style.display = 'block';
return localStorage.setItem('showReminder', true);
}
}
EventBus.dispatch('refresh', this.props.category);
}
resetItem = () => {
localStorage.setItem(this.props.name, this.props.default);
this.setState({
value: this.props.default,
numberWidth: ((this.props.default.length + 1) * this.widthCalculation)
this.handleChange({
target: {
value: this.props.default || ''
}
});
toast(window.language.toasts.reset);
EventBus.dispatch('refresh', this.props.category);
toast(variables.language.getMessage(variables.languagecode, 'toasts.reset'));
}
render() {
const text = <input className='sliderText' type='number' min={this.props.min} max={this.props.max} onChange={(e) => this.handleChange(e, 'text')} value={this.state.value} style={{ width: this.state.numberWidth }}/>;
return (
<>
<p>{this.props.title} ({text}{this.props.display}) <span className='modalLink' onClick={this.resetItem}>{this.language.buttons.reset}</span></p>
<input className='range' type='range' min={this.props.min} max={this.props.max} step={this.props.step || 1} value={this.state.value} onChange={this.handleChange} />
<p>{this.props.title}<span className='modalLink' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span></p>
<Slider
value={Number(this.state.value)}
onChange={this.handleChange}
valueLabelDisplay='auto'
default={Number(this.props.default)}
min={Number(this.props.min)}
max={Number(this.props.max)}
step={Number(this.props.step) || 1}
getAriaValueText={(value) => `${value}`}
marks={this.props.marks || []}
/>
</>
);
}

View File

@@ -1,12 +1,10 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { Switch as SwitchUI, FormControlLabel } from '@mui/material';
import EventBus from '../../../../modules/helpers/eventbus';
import SettingsFunctions from '../../../../modules/helpers/settings';
import EventBus from 'modules/helpers/eventbus';
import SwitchUI from '@material-ui/core/Switch';
import FormControlLabel from '@material-ui/core/FormControlLabel';
export default class Switch extends React.PureComponent {
export default class Switch extends PureComponent {
constructor(props) {
super(props);
this.state = {
@@ -15,12 +13,15 @@ export default class Switch extends React.PureComponent {
}
handleChange = () => {
SettingsFunctions.setItem(this.props.name);
const value = (this.state.checked === true) ? false : true;
localStorage.setItem(this.props.name, value);
this.setState({
checked: (this.state.checked === true) ? false : true
checked: value
});
variables.stats.postEvent('setting', `${this.props.name} ${(this.state.checked === true) ? 'enabled' : 'disabled'}`);
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
document.querySelector('.reminder-info').style.display = 'block';
@@ -32,22 +33,13 @@ export default class Switch extends React.PureComponent {
}
render() {
let text = this.props.text;
if (this.props.newFeature) {
text = <>{this.props.text} <span className='newFeature'> NEW</span></>;
} else if (this.props.betaFeature) {
text = <>{this.props.text} <span className='newFeature'> BETA</span></>;
}
return (
<>
<FormControlLabel
control={<SwitchUI name={this.props.name} color='primary' checked={this.state.checked} onChange={this.handleChange} />}
label={text}
label={this.props.text}
labelPlacement='start'
/>
<br/>
</>
);
}

View File

@@ -1,16 +1,16 @@
import React from 'react';
import EventBus from '../../../../modules/helpers/eventbus';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { TextField } from '@mui/material';
export default class Text extends React.PureComponent {
import EventBus from 'modules/helpers/eventbus';
export default class Text extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || ''
};
this.language = window.language.modals.main.settings;
}
handleChange = (e) => {
@@ -23,7 +23,7 @@ export default class Text extends React.PureComponent {
localStorage.setItem(this.props.name, value);
this.setState({
value: value
value
});
if (this.props.element) {
@@ -37,23 +37,22 @@ export default class Text extends React.PureComponent {
}
resetItem = () => {
localStorage.setItem(this.props.name, this.props.default || '');
this.setState({
value: this.props.default || ''
this.handleChange({
target: {
value: this.props.default || ''
}
});
toast(window.language.toasts.reset);
EventBus.dispatch('refresh', this.props.category);
toast(variables.language.getMessage(variables.languagecode, 'toasts.reset'));
}
render() {
return (
<>
<p>{this.props.title} <span className='modalLink' onClick={this.resetItem}>{this.language.buttons.reset}</span></p>
{(this.props.textarea === true) ?
<textarea className='settingsTextarea' spellCheck={false} value={this.state.value} onChange={this.handleChange}/>
: <input type='text' value={this.state.value} onChange={this.handleChange}/>
{(this.props.textarea === true) ?
<TextField label={this.props.title} value={this.state.value} onChange={this.handleChange} varient='outlined' multiline spellCheck={false} minRows={4} maxRows={10} InputLabelProps={{ shrink: true }} />
: <TextField label={this.props.title} value={this.state.value} onChange={this.handleChange} varient='outlined' InputLabelProps={{ shrink: true }} />
}
<span className='modalLink' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span>
</>
);
}

View File

@@ -1,63 +1,67 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { Email, Twitter, Chat, Instagram, Facebook } from '@mui/icons-material';
import Tooltip from '../../../../helpers/tooltip/Tooltip';
import EmailIcon from '@material-ui/icons/Email';
import TwitterIcon from '@material-ui/icons/Twitter';
import ForumIcon from '@material-ui/icons/Forum';
import Tooltip from 'components/helpers/tooltip/Tooltip';
const other_contributors = require('../../../../../modules/other_contributors.json');
const other_contributors = require('modules/other_contributors.json');
export default class About extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
export default class About extends React.PureComponent {
constructor() {
super();
this.state = {
contributors: [],
sponsors: [],
other_contributors: [],
photographers: [],
update: window.language.modals.main.settings.sections.about.version.checking_update,
loading: window.language.modals.main.loading
photographers: this.getMessage('modals.main.loading'),
update: this.getMessage('modals.main.settings.sections.about.version.checking_update'),
loading: this.getMessage('modals.main.loading')
};
this.language = window.language.modals.main.settings.sections.about;
this.controller = new AbortController();
}
async getGitHubData() {
let contributors, sponsors, photographers, versionData;
try {
contributors = await (await fetch(window.constants.GITHUB_URL + '/repos/mue/mue/contributors', { signal: this.controller.signal })).json();
sponsors = (await (await fetch(window.constants.SPONSORS_URL + '/list', { signal: this.controller.signal })).json()).sponsors;
photographers = await (await fetch(window.constants.API_URL + '/images/photographers', { signal: this.controller.signal })).json();
versionData = await (await fetch(window.constants.GITHUB_URL + '/repos/mue/mue/releases', { signal: this.controller.signal })).json();
versionData = await (await fetch(variables.constants.GITHUB_URL + '/repos/' + variables.constants.ORG_NAME + '/' + variables.constants.REPO_NAME + '/releases', { signal: this.controller.signal })).json();
contributors = await (await fetch(variables.constants.GITHUB_URL + '/repos/'+ variables.constants.ORG_NAME + '/' + variables.constants.REPO_NAME + '/contributors', { signal: this.controller.signal })).json();
sponsors = (await (await fetch(variables.constants.SPONSORS_URL + '/list', { signal: this.controller.signal })).json()).sponsors;
photographers = await (await fetch(variables.constants.API_URL + '/images/photographers', { signal: this.controller.signal })).json();
} catch (e) {
if (this.controller.signal.aborted === true) {
return;
}
return this.setState({
update: this.language.version.error.title,
loading: this.language.version.error.description
update: this.getMessage('modals.main.settings.sections.about.version.error.title'),
loading: this.getMessage('modals.main.settings.sections.about.version.error.description')
});
}
if (sponsors.length === 0) {
sponsors = [{ handle: 'empty' }];
}
if (this.controller.signal.aborted === true) {
return;
}
const newVersion = versionData[0].tag_name;
let updateMsg = this.language.version.no_update;
if (Number(window.constants.VERSION) < newVersion) {
updateMsg = `${this.language.version.update_available}: ${newVersion}`;
let update = this.getMessage('modals.main.settings.sections.about.version.no_update');
if (Number(variables.constants.VERSION.replaceAll('.', '')) < Number(newVersion.replaceAll('.', ''))) {
update = `${this.getMessage('modals.main.settings.sections.about.version.update_available')}: ${newVersion}`;
}
this.setState({
// exclude bots
contributors: contributors.filter((contributor) => !contributor.login.includes('bot')),
sponsors: sponsors,
update: updateMsg,
other_contributors: other_contributors,
sponsors,
update,
other_contributors,
photographers: photographers.sort().join(', '),
loading: null
});
@@ -66,8 +70,8 @@ export default class About extends React.PureComponent {
componentDidMount() {
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
this.setState({
update: this.language.version.offline_mode,
loading: window.language.modals.main.marketplace.offline.description
update: this.getMessage('modals.main.settings.sections.about.version.checking_update'),
loading: this.getMessage('modals.main.marketplace.offline.description')
});
return;
}
@@ -83,49 +87,62 @@ export default class About extends React.PureComponent {
render() {
return (
<>
<h2>{this.language.title}</h2>
<img draggable='false' style={{'height': '100px', 'width': 'auto'}} src='./././icons/logo_horizontal.png' alt='Mue logo'></img>
<p>{this.language.copyright} 2018-{new Date().getFullYear()} Mue Tab (BSD-3 License)</p>
<p>{this.language.version.title} {window.constants.VERSION} ({this.state.update})</p>
<h2>{this.getMessage('modals.main.settings.sections.about.title')}</h2>
<img draggable='false' className='aboutLogo' src='./././icons/logo_horizontal.png' alt='Logo'></img>
<p>{this.getMessage('modals.main.settings.sections.about.copyright')} {variables.constants.COPYRIGHT_YEAR}-{new Date().getFullYear()} <a href={'https://github.com/' + variables.constants.ORG_NAME + '/' + variables.constants.REPO_NAME + '/graphs/contributors'} className='aboutLink' target='_blank' rel='noopener noreferrer'>{variables.constants.COPYRIGHT_NAME}</a> ({variables.constants.COPYRIGHT_LICENSE})</p>
<p>{this.getMessage('modals.main.settings.sections.about.version.title')} {variables.constants.VERSION} ({this.state.update})</p>
<a href={variables.constants.PRIVACY_URL} className='aboutLink' target='_blank' rel='noopener noreferrer' style={{ fontSize: '1rem' }}>{this.getMessage('modals.welcome.sections.privacy.links.privacy_policy')}</a>
<h3>{this.language.contact_us}</h3>
<a href='mailto:hello@muetab.com' className='aboutIcon' target='_blank' rel='noopener noreferrer'><EmailIcon/></a>
<a href='https://twitter.com/getmue' className='aboutIcon' target='_blank' rel='noopener noreferrer'><TwitterIcon/></a>
<a href='https://discord.gg/zv8C9F8' className='aboutIcon' target='_blank' rel='noopener noreferrer'><ForumIcon/></a>
<h3>{this.getMessage('modals.main.settings.sections.about.contact_us')}</h3>
<a href={'mailto:' + variables.constants.EMAIL} className='aboutIcon' target='_blank' rel='noopener noreferrer'><Email/></a>
<a href={'https://twitter.com/' + variables.constants.TWITTER_HANDLE} className='aboutIcon' target='_blank' rel='noopener noreferrer'><Twitter/></a>
<a href={'https://instagram.com/' + variables.constants.INSTAGRAM_HANDLE} className='aboutIcon' target='_blank' rel='noopener noreferrer'><Instagram/></a>
<a href={'https://facebook.com/' + variables.constants.FACEBOOK_HANDLE} className='aboutIcon' target='_blank' rel='noopener noreferrer'><Facebook/></a>
<a href={'https://discord.gg/' + variables.constants.DISCORD_SERVER} className='aboutIcon' target='_blank' rel='noopener noreferrer'><Chat/></a>
<h3>{this.language.support_mue}</h3>
<p><a href='https://github.com/sponsors/davidjcralph' className='aboutLink' target='_blank' rel='noopener noreferrer'>GitHub Sponsors</a> <a href='https://ko-fi.com/davidjcralph' className='aboutLink' target='_blank' rel='noopener noreferrer'>Ko-Fi</a> <a href='https://patreon.com/davidjcralph' className='aboutLink' target='_blank' rel='noopener noreferrer'>Patreon</a></p>
<h3>{this.getMessage('modals.main.settings.sections.about.support_mue')}</h3>
<p>
<a href={'https://github.com/sponsors/' + variables.constants.DONATE_USERNAME} className='aboutLink' target='_blank' rel='noopener noreferrer'>GitHub Sponsors</a>
&nbsp; &nbsp;<a href={'https://ko-fi.com/' + variables.constants.DONATE_USERNAME} className='aboutLink' target='_blank' rel='noopener noreferrer'>Ko-Fi</a>
&nbsp; &nbsp;<a href={'https://patreon.com/' + variables.constants.DONATE_USERNAME} className='aboutLink' target='_blank' rel='noopener noreferrer'>Patreon</a>
</p>
<h3>{this.language.resources_used.title}</h3>
<p>Pexels ({this.language.resources_used.bg_images})</p>
<p>Unsplash ({this.language.resources_used.bg_images})</p>
<p>Google ({this.language.resources_used.pin_icon})</p>
<p>Undraw ({this.language.resources_used.welcome_img})</p>
<h3>{this.getMessage('modals.main.settings.sections.about.resources_used.title')}</h3>
<p>
<a href='https://www.pexels.com' className='aboutLink' target='_blank' rel='noopener noreferrer'>Pexels</a>
, <a href='https://unsplash.com' className='aboutLink' target='_blank' rel='noopener noreferrer'>Unsplash</a> ({this.getMessage('modals.main.settings.sections.about.resources_used.bg_images')})
</p>
<p><a href='https://undraw.co' className='aboutLink' target='_blank' rel='noopener noreferrer'>Undraw</a> ({this.getMessage('modals.main.settings.sections.about.resources_used.welcome_img')})</p>
<h3>{this.language.contributors}</h3>
<h3>{this.getMessage('modals.main.settings.sections.about.contributors')}</h3>
<p>{this.state.loading}</p>
{this.state.contributors.map((item) => (
<Tooltip title={item.login} key={item.login}>
<a href={'https://github.com/' + item.login} target='_blank' rel='noopener noreferrer'><img draggable='false' className='abouticon' src={item.avatar_url + '&size=128'} alt={item.login}/></a>
{this.state.contributors.map(({ login, id }) => (
<Tooltip title={login} key={login}>
<a href={'https://github.com/' + login} target='_blank' rel='noopener noreferrer'><img draggable='false' className='abouticon' src={'https://avatars.githubusercontent.com/u/' + id + '?s=128'} alt={login}></img></a>
</Tooltip>
))}
{ // for those who contributed without opening a pull request
this.state.other_contributors.map((item) => (
<Tooltip title={item.login} key={item.login}>
<a href={'https://github.com/' + item.login} target='_blank' rel='noopener noreferrer'><img draggable='false' className='abouticon' src={item.avatar_url + '&size=128'} alt={item.login}/></a>
this.state.other_contributors.map(({ login, avatar_url }) => (
<Tooltip title={login} key={login}>
<a href={'https://github.com/' + login} target='_blank' rel='noopener noreferrer'><img draggable='false' className='abouticon' src={avatar_url + '&s=128'} alt={login}></img></a>
</Tooltip>
))}
<h3>{this.language.supporters}</h3>
<h3>{this.getMessage('modals.main.settings.sections.about.supporters')}</h3>
<p>{this.state.loading}</p>
{this.state.sponsors.map((item) => (
<Tooltip title={item.handle} key={item.handle}>
<a href={item.profile} target='_blank' rel='noopener noreferrer'><img draggable='false' className='abouticon' src={item.avatar + '&size=128'} alt={item.handle}></img></a>
</Tooltip>
))}
{this.state.sponsors.map(({ handle, avatar }) => {
if (handle === 'empty') {
return <p>{this.getMessage('modals.main.settings.sections.about.no_supporters')}</p>;
}
<h3>{this.language.photographers}</h3>
<p>{this.state.loading}</p>
return (
<Tooltip title={handle} key={handle}>
<a href={'https://github.com/' + handle} target='_blank' rel='noopener noreferrer'><img draggable='false' className='abouticon' src={avatar.split('?')[0] + '?s=128'} alt={handle}></img></a>
</Tooltip>
)
})}
<h3>{this.getMessage('modals.main.settings.sections.about.photographers')}</h3>
<p>{this.state.photographers}</p>
</>
);

View File

@@ -1,59 +1,76 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Modal from 'react-modal';
import { MenuItem } from '@mui/material';
import { Upload as ImportIcon, Download as ExportIcon, RestartAlt as ResetIcon } from '@mui/icons-material';
import { exportSettings, importSettings } from 'modules/helpers/settings/modals';
import Checkbox from '../Checkbox';
import FileUpload from '../FileUpload';
import Text from '../Text';
import Switch from '../Switch';
import ResetModal from '../ResetModal';
import Dropdown from '../Dropdown';
import SettingsFunctions from '../../../../../modules/helpers/settings';
const time_zones = require('components/widgets/time/timezones.json');
import { toast } from 'react-toastify';
import Modal from 'react-modal';
export default class AdvancedSettings extends React.PureComponent {
export default class AdvancedSettings extends PureComponent {
constructor() {
super();
this.state = {
resetModal: false
};
this.language = window.language.modals.main.settings;
}
settingsImport(e) {
const content = JSON.parse(e.target.result);
Object.keys(content).forEach((key) => {
localStorage.setItem(key, content[key]);
});
toast(window.language.toasts.imported);
}
render() {
const { advanced } = this.language.sections;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<>
<h2>{advanced.title}</h2>
<Checkbox name='offlineMode' text={advanced.offline_mode} element='.other' />
<h2>{getMessage('modals.main.settings.sections.advanced.title')}</h2>
<Checkbox name='offlineMode' text={getMessage('modals.main.settings.sections.advanced.offline_mode')} element='.other' />
<Dropdown name='timezone' label={getMessage('modals.main.settings.sections.advanced.timezone.title')} category='timezone' manual={true}>
<MenuItem value='auto'>{getMessage('modals.main.settings.sections.advanced.timezone.automatic')}</MenuItem>
{time_zones.map((timezone) => (
<MenuItem value={timezone} key={timezone}>{timezone}</MenuItem>
))}
</Dropdown>
<h3>{advanced.data}</h3>
<button className='reset' onClick={() => this.setState({ resetModal: true })}>{this.language.buttons.reset}</button>
<button className='export' onClick={() => SettingsFunctions.exportSettings()}>{this.language.buttons.export}</button>
<button className='import' onClick={() => document.getElementById('file-input').click()}>{this.language.buttons.import}</button>
<FileUpload id='file-input' accept='application/json' type='settings' loadFunction={(e) => this.settingsImport(e)}/>
{localStorage.getItem('welcomePreview') !== 'true' ?
<>
<h3>{getMessage('modals.main.settings.sections.advanced.data')}</h3>
<br/>
<div className='data-buttons-row'>
<button onClick={() => this.setState({ resetModal: true })}>
{getMessage('modals.main.settings.buttons.reset')}
<ResetIcon/>
</button>
<button onClick={() => exportSettings()}>
{getMessage('modals.main.settings.buttons.export')}
<ExportIcon/>
</button>
<button onClick={() => document.getElementById('file-input').click()}>
{getMessage('modals.main.settings.buttons.import')}
<ImportIcon/>
</button>
</div>
</>
: null}
<FileUpload id='file-input' accept='application/json' type='settings' loadFunction={(e) => importSettings(e)}/>
<h3>{advanced.customisation}</h3>
<Text title={advanced.tab_name} name='tabName' default={window.language.tabname} category='other'/>
<Text title={advanced.custom_js} name='customjs' textarea={true} element='.other'/>
<Text title={advanced.custom_css} name='customcss' textarea={true} element='.other'/>
<h3>{getMessage('modals.main.settings.sections.advanced.customisation')}</h3>
<Text title={getMessage('modals.main.settings.sections.advanced.tab_name')} name='tabName' default={getMessage('tabname')} category='other'/>
{window.location.href.startsWith('http://') || window.location.href.startsWith('https://') ?
<Text title={getMessage('modals.main.settings.sections.advanced.custom_js')} name='customjs' textarea={true} category='other' element='other'/>
: null}
<Text title={getMessage('modals.main.settings.sections.advanced.custom_css')} name='customcss' textarea={true} category='other'/>
<h3>{this.language.sections.experimental.title}</h3>
<p style={{ 'maxWidth': '75%'}}>{advanced.experimental_warning}</p>
<Switch name='experimental' text={this.language.enabled} element='.other'/>
<h3>{getMessage('modals.main.settings.sections.experimental.title')}</h3>
<p style={{ maxWidth: '75%' }}>{getMessage('modals.main.settings.sections.advanced.experimental_warning')}</p>
<Switch name='experimental' text={getMessage('modals.main.settings.enabled')} element='.other'/>
<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ resetModal: false })} isOpen={this.state.resetModal} className='Modal resetmodal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ resetModal: false })} isOpen={this.state.resetModal} className='Modal resetmodal mainModal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<ResetModal modalClose={() => this.setState({ resetModal: false })} />
</Modal>
</>

View File

@@ -1,6 +1,4 @@
import React from 'react';
import { engineName } from 'react-device-detect';
import variables from 'modules/variables';
import Checkbox from '../Checkbox';
import Dropdown from '../Dropdown';
@@ -8,60 +6,57 @@ import Radio from '../Radio';
import Slider from '../Slider';
import Text from '../Text';
import { values } from 'modules/helpers/settings/modals';
export default function AppearanceSettings() {
const { appearance } = window.language.modals.main.settings.sections;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
const themeOptions = [
{
'name': appearance.theme.auto,
'value': 'auto'
name: getMessage('modals.main.settings.sections.appearance.theme.auto'),
value: 'auto'
},
{
'name': appearance.theme.light,
'value': 'light'
name: getMessage('modals.main.settings.sections.appearance.theme.light'),
value: 'light'
},
{
'name': appearance.theme.dark,
'value': 'dark'
name: getMessage('modals.main.settings.sections.appearance.theme.dark'),
value: 'dark'
}
];
return (
<>
<h2>{appearance.title}</h2>
<Radio name='theme' title={appearance.theme.title} options={themeOptions} category='other' />
<h2>{getMessage('modals.main.settings.sections.appearance.title')}</h2>
<Radio name='theme' title={getMessage('modals.main.settings.sections.appearance.theme.title')} options={themeOptions} category='other' />
<h3>{appearance.navbar.title}</h3>
<Checkbox name='notesEnabled' text={appearance.navbar.notes} element='.other' />
<Checkbox name='refresh' text={appearance.navbar.refresh} element='.other' />
<h3>{appearance.font.title}</h3>
<Text title={appearance.font.custom} name='font' upperCaseFirst={true} element='.other' />
<h3>{getMessage('modals.main.settings.sections.appearance.font.title')}</h3>
<Text title={getMessage('modals.main.settings.sections.appearance.font.custom')} name='font' upperCaseFirst={true} category='other' />
<br/>
<Checkbox name='fontGoogle' text={appearance.font.google} element='.other' />
<Dropdown label={appearance.font.weight.title} name='fontweight' element='.other'>
<Checkbox name='fontGoogle' text={getMessage('modals.main.settings.sections.appearance.font.google')} category='other' />
<Dropdown label={getMessage('modals.main.settings.sections.appearance.font.weight.title')} name='fontweight' category='other'>
{/* names are taken from https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight */}
<option value='100'>{appearance.font.weight.thin}</option>
<option value='200'>{appearance.font.weight.extra_light}</option>
<option value='300'>{appearance.font.weight.light}</option>
<option value='400'>{appearance.font.weight.normal}</option>
<option value='500'>{appearance.font.weight.medium}</option>
<option value='600'>{appearance.font.weight.semi_bold}</option>
<option value='700'>{appearance.font.weight.bold}</option>
<option value='800'>{appearance.font.weight.extra_bold}</option>
<option value='100'>{getMessage('modals.main.settings.sections.appearance.font.weight.thin')}</option>
<option value='200'>{getMessage('modals.main.settings.sections.appearance.font.weight.extra_light')}</option>
<option value='300'>{getMessage('modals.main.settings.sections.appearance.font.weight.light')}</option>
<option value='400'>{getMessage('modals.main.settings.sections.appearance.font.weight.normal')}</option>
<option value='500'>{getMessage('modals.main.settings.sections.appearance.font.weight.medium')}</option>
<option value='600'>{getMessage('modals.main.settings.sections.appearance.font.weight.semi_bold')}</option>
<option value='700'>{getMessage('modals.main.settings.sections.appearance.font.weight.bold')}</option>
<option value='800'>{getMessage('modals.main.settings.sections.appearance.font.weight.extra_bold')}</option>
</Dropdown>
<br/><br/>
<Dropdown label={appearance.font.style.title} name='fontstyle' element='.other'>
<option value='normal'>{appearance.font.style.normal}</option>
<option value='italic'>{appearance.font.style.italic}</option>
<option value='oblique'>{appearance.font.style.oblique}</option>
<Dropdown label={getMessage('modals.main.settings.sections.appearance.font.style.title')} name='fontstyle' category='other'>
<option value='normal'>{getMessage('modals.main.settings.sections.appearance.font.style.normal')}</option>
<option value='italic'>{getMessage('modals.main.settings.sections.appearance.font.style.italic')}</option>
<option value='oblique'>{getMessage('modals.main.settings.sections.appearance.font.style.oblique')}</option>
</Dropdown>
<h3>{appearance.accessibility.title}</h3>
{(engineName === 'Blink') ?
<Slider title={appearance.accessibility.widget_zoom} name='widgetzoom' default='100' step='10' min='50' max='200' display='%' category='other'/>
: null}
<Slider title={appearance.accessibility.toast_duration} name='toastDisplayTime' default='2500' step='100' min='500' max='5000' toast={true} display={' ' + appearance.accessibility.milliseconds} />
<h3>{getMessage('modals.main.settings.sections.appearance.accessibility.title')}</h3>
<Checkbox text={getMessage('modals.main.settings.sections.appearance.accessibility.text_shadow')} name='textBorder' category='other'/>
<Checkbox text={getMessage('modals.main.settings.sections.appearance.accessibility.animations')} name='animations' category='other'/>
<Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.toast_duration')} name='toastDisplayTime' default='2500' step='100' min='500' max='5000' marks={values('toast')} toast={true}
display={' ' + getMessage('modals.main.settings.sections.appearance.accessibility.milliseconds')} />
</>
);
}

View File

@@ -1,12 +1,11 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent, createRef } from 'react';
import { WifiOff } from '@mui/icons-material';
import Modal from 'react-modal';
//import Modal from 'react-modal';
import Lightbox from '../../marketplace/Lightbox';
//import Lightbox from '../../marketplace/Lightbox';
import WifiOffIcon from '@material-ui/icons/WifiOff';
export default class Changelog extends React.PureComponent {
export default class Changelog extends PureComponent {
constructor() {
super();
this.state = {
@@ -14,36 +13,40 @@ export default class Changelog extends React.PureComponent {
showLightbox: false,
lightboxImg: null
};
this.language = window.language.modals.update;
this.offlineMode = (localStorage.getItem('offlineMode') === 'true');
this.controller = new AbortController();
this.changelog = createRef();
}
async getUpdate() {
const data = await (await fetch(window.constants.BLOG_POST + '/index.json', { signal: this.controller.signal })).json();
const data = await (await fetch(variables.constants.BLOG_POST + '/index.json', { signal: this.controller.signal })).json();
if (this.controller.signal.aborted === true) {
return;
}
let date = new Date(data.date);
date = date.toLocaleDateString(window.languagecode.replace('_', '-'), {
year: 'numeric', month: 'long', day: 'numeric'
let date = new Date(data.date.split(' ')[0]);
date = date.toLocaleDateString(variables.languagecode.replace('_', '-'), {
year: 'numeric',
month: 'long',
day: 'numeric'
});
this.setState({
title: data.title,
date: date,
date,
image: data.featured_image || null,
author: 'By ' + data.authors.join(', '),
author: variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.changelog.by', {
author: data.authors.join(', ')
}),
html: data.html
});
// lightbox etc
const content = document.querySelector('.tab-content');
const images = content.getElementsByTagName('img');
const links = content.getElementsByTagName('a');
const images = this.changelog.current.getElementsByTagName('img');
const links = this.changelog.current.getElementsByTagName('a');
for (let img of images) {
for (const img of images) {
img.draggable = false;
img.onclick = () => {
this.setState({
@@ -53,6 +56,7 @@ export default class Changelog extends React.PureComponent {
};
}
// open in new tab
for (let link = 0; link < links.length; link++) {
links[link].target = '_blank';
links[link].rel = 'noopener noreferrer';
@@ -60,7 +64,7 @@ export default class Changelog extends React.PureComponent {
}
componentDidMount() {
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
if (navigator.onLine === false || this.offlineMode) {
return;
}
@@ -73,6 +77,8 @@ export default class Changelog extends React.PureComponent {
}
render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
const errorMessage = (msg) => {
return (
<div className='emptyitems'>
@@ -83,29 +89,27 @@ export default class Changelog extends React.PureComponent {
);
};
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
const language = window.language.modals.main.marketplace;
if (navigator.onLine === false || this.offlineMode) {
return errorMessage(<>
<WifiOffIcon/>
<h1>{language.offline.title}</h1>
<p className='description'>{language.offline.description}</p>
<WifiOff/>
<h1>{getMessage('modals.main.marketplace.offline.title')}</h1>
<p className='description'>{getMessage('modals.main.marketplace.offline.description')}</p>
</>);
}
if (!this.state.title) {
return errorMessage(<h1>{window.language.modals.main.loading}</h1>);
return errorMessage(<h1>{getMessage('modals.main.loading')}</h1>);
}
return (
<div className='changelogtab'>
<h1 style={{ 'marginBottom': '-10px' }}>{this.state.title}</h1>
<h5 style={{ 'lineHeight': '0px' }}>{this.state.author} {this.state.date}</h5>
{this.state.image ? <img draggable='false' src={this.state.image} alt={window.language.modals.update.title} className='updateimage'/> : null}
<div className='changelogtab' ref={this.changelog}>
<h1>{this.state.title}</h1>
<h5>{this.state.author} {this.state.date}</h5>
{this.state.image ? <img draggable='false' src={this.state.image} alt={this.state.title} className='updateimage'/> : null}
<div className='updatechangelog' dangerouslySetInnerHTML={{ __html: this.state.html }}/>
{/*<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ showLightbox: false })} isOpen={this.state.showLightbox} className='Modal lightboxmodal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<Modal closeTimeoutMS={100} onRequestClose={() => this.setState({ showLightbox: false })} isOpen={this.state.showLightbox} className='Modal lightboxmodal' overlayClassName='Overlay resetoverlay' ariaHideApp={false}>
<Lightbox modalClose={() => this.setState({ showLightbox: false })} img={this.state.lightboxImg}/>
</Modal>*/}
</Modal>
</div>
);
}

View File

@@ -0,0 +1,66 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Header from '../Header';
import Checkbox from '../Checkbox';
import Dropdown from '../Dropdown';
export default class DateSettings extends PureComponent {
constructor() {
super();
this.state = {
dateType: localStorage.getItem('dateType') || 'long'
};
}
render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
let dateSettings;
const longSettings = (
<>
<Checkbox name='dayofweek' text={getMessage('modals.main.settings.sections.date.day_of_week')} category='date' />
<Checkbox name='datenth' text={getMessage('modals.main.settings.sections.date.datenth')} category='date' />
</>
);
const shortSettings = (
<>
<Dropdown label={getMessage('modals.main.settings.sections.date.short_format')} name='dateFormat' category='date'>
<option value='DMY'>DMY</option>
<option value='MDY'>MDY</option>
<option value='YMD'>YMD</option>
</Dropdown>
<Dropdown label={getMessage('modals.main.settings.sections.date.short_separator.title')} name='shortFormat' category='date'>
<option value='dash'>{getMessage('modals.main.settings.sections.date.short_separator.dash')}</option>
<option value='dots'>{getMessage('modals.main.settings.sections.date.short_separator.dots')}</option>
<option value='gaps'>{getMessage('modals.main.settings.sections.date.short_separator.gaps')}</option>
<option value='slashes'>{getMessage('modals.main.settings.sections.date.short_separator.slashes')}</option>
</Dropdown>
</>
);
switch (this.state.dateType) {
case 'short': dateSettings = shortSettings; break;
case 'long': dateSettings = longSettings; break;
default: break;
}
return (
<>
<Header title={getMessage('modals.main.settings.sections.date.title')} setting='date' category='date' element='.date' zoomSetting='zoomDate'/>
<Checkbox name='weeknumber' text={getMessage('modals.main.settings.sections.date.week_number')} category='date'/>
<Dropdown label={getMessage('modals.main.settings.sections.time.type')} name='dateType' onChange={(value) => this.setState({ dateType: value })} category='date'>
<option value='long'>{getMessage('modals.main.settings.sections.date.type.long')}</option>
<option value='short'>{getMessage('modals.main.settings.sections.date.type.short')}</option>
</Dropdown>
<Checkbox name='datezero' text={getMessage('modals.main.settings.sections.time.digital.zero')} category='date'/>
{dateSettings}
</>
);
}
}

View File

@@ -1,31 +1,31 @@
import React from 'react';
import variables from 'modules/variables';
import { useState } from 'react';
import Checkbox from '../Checkbox';
import Slider from '../Slider';
//import Text from '../Text';
import { TextField } from '@mui/material';
import EventBus from 'modules/helpers/eventbus';
import { values } from 'modules/helpers/settings/modals';
export default function ExperimentalSettings() {
const { experimental } = window.language.modals.main.settings.sections;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
const [eventType, setEventType] = useState();
const [eventName, setEventName] = useState();
return (
<>
<h2>{experimental.title}</h2>
<p>{experimental.warning}</p>
<Checkbox name='animations' text={window.language.modals.main.settings.sections.appearance.animations} element='.other'/>
<h3>{experimental.developer}</h3>
<h2>{getMessage('modals.main.settings.sections.experimental.title')}</h2>
<p>{getMessage('modals.main.settings.sections.experimental.warning')}</p>
<h3>{getMessage('modals.main.settings.sections.experimental.developer')}</h3>
<Checkbox name='debug' text='Debug hotkey (Ctrl + #)' element='.other'/>
<Slider title='Debug timeout' name='debugtimeout' min='0' max='5000' default='0' step='100' display=' miliseconds' element='.other' />
{/* <Checkbox name='beta' text='Beta Mode Override'/>
<Text name='api_override' title='Version Override (format example: 5.0)'/>
<Text name='api_override' title='API URL Override'/>
<Text name='marketplace_override' title='Marketplace URL Override'/>
<Text name='unsplash_override' title='Unsplash URL Override'/>
<Text name='sponsors_override' title='Sponsors URL Override'/>
<Text name='github_override' title='GitHub URL Override'/>
<Slider title='Debug timeout' name='debugtimeout' min='0' max='5000' default='0' step='100' marks={values('experimental')} element='.other' />
<p>Send Event</p>
<TextField label={'Type'} value={eventType} onChange={(e) => setEventType(e.target.value)} spellCheck={false} varient='outlined' InputLabelProps={{ shrink: true }} />
<TextField label={'Name'} value={eventName} onChange={(e) => setEventName(e.target.value)} spellCheck={false} varient='outlined' InputLabelProps={{ shrink: true }} />
<br/>
<button className='uploadbg' onClick={() => EventBus.dispatch(eventType, eventName)}>Send</button>
<br/><br/>
*/}
<br/><br/>
<button className='reset' style={{'marginLeft': '0px'}} onClick={() => localStorage.clear()}>Clear LocalStorage</button>
<button className='reset' style={{ marginLeft: '0px' }} onClick={() => localStorage.clear()}>Clear LocalStorage</button>
</>
);
}

View File

@@ -1,45 +1,43 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Header from '../Header';
import Checkbox from '../Checkbox';
import Switch from '../Switch';
import Text from '../Text';
import DayPickerInput from 'react-day-picker/DayPickerInput';
import 'react-day-picker/lib/style.css';
export default class GreetingSettings extends React.PureComponent {
export default class GreetingSettings extends PureComponent {
constructor() {
super();
this.state = {
birthday: new Date(localStorage.getItem('birthday')) || new Date()
};
this.language = window.language.modals.main.settings;
}
changeDate = (data) => {
localStorage.setItem('birthday', data);
changeDate = (e) => {
localStorage.setItem('birthday', e.target.value);
this.setState({
birthday: data
birthday: new Date(e.target.value)
});
}
render() {
const { greeting } = this.language.sections;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<>
<h2>{greeting.title}</h2>
<Switch name='greeting' text={this.language.enabled} category='greeting' element='.greeting'/>
<Checkbox name='events' text={greeting.events} category='greeting' element='.greeting'/>
<Checkbox name='defaultGreetingMessage' text={greeting.default} category='greeting' element='.greeting'/>
<Text title={greeting.name} name='greetingName' category='greeting' element='.greeting'/>
<Header title={getMessage('modals.main.settings.sections.greeting.title')} setting='greeting' category='greeting' element='.greeting' zoomSetting='zoomGreeting'/>
<Checkbox name='events' text={getMessage('modals.main.settings.sections.greeting.events')} category='greeting'/>
<Checkbox name='defaultGreetingMessage' text={getMessage('modals.main.settings.sections.greeting.default')} category='greeting'/>
<Text title={getMessage('modals.main.settings.sections.greeting.name')} name='greetingName' category='greeting'/>
<h3>{greeting.birthday}</h3>
<Switch name='birthdayenabled' text={this.language.enabled} category='greeting' element='.greeting'/>
<Checkbox name='birthdayage' text={greeting.birthday_age} category='greeting' element='.greeting'/>
<p>{greeting.birthday_date}</p>
<DayPickerInput onDayChange={this.changeDate} value={this.state.birthday}/>
<h3>{getMessage('modals.main.settings.sections.greeting.birthday')}</h3>
<Switch name='birthdayenabled' text={getMessage('modals.main.settings.enabled')} category='greeting'/>
<br/>
<Checkbox name='birthdayage' text={getMessage('modals.main.settings.sections.greeting.birthday_age')} category='greeting'/>
<p>{getMessage('modals.main.settings.sections.greeting.birthday_date')}</p>
<input type='date' onChange={this.changeDate} value={this.state.birthday.toISOString().substr(0, 10)} required/>
</>
);
}

View File

@@ -0,0 +1,148 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Header from '../Header';
import KeybindInput from '../KeybindInput';
export default class KeybindSettings extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
constructor() {
super();
this.state = {
keybinds: JSON.parse(localStorage.getItem('keybinds')) || {},
cancelled: false
};
}
showReminder() {
document.querySelector('.reminder-info').style.display = 'none';
return localStorage.setItem('showReminder', false);
}
listen(type) {
const currentKeybinds = this.state.keybinds;
currentKeybinds[type] = this.getMessage('modals.main.settings.sections.keybinds.recording');
this.setState({
keybinds: currentKeybinds,
cancelled: false
});
this.forceUpdate();
let keys = '';
let previouskey = '';
this.keydown = document.addEventListener('keydown', (event) => {
if (event.key === previouskey && this.state.cancelled === true) {
return;
}
if (keys === '') {
keys = event.key;
} else {
keys = `${keys}+${event.key}`;
}
previouskey = event.key
});
this.keyup = document.addEventListener('keyup', () => {
if (this.state.cancelled === true) {
return;
}
document.removeEventListener('keydown', this.keydown);
const keybinds = this.state.keybinds;
keybinds[type] = keys.split('+').slice(0, 4).join('+');
localStorage.setItem('keybinds', JSON.stringify(keybinds));
this.setState({
keybinds: JSON.parse(localStorage.getItem('keybinds')) || {}
});
});
document.removeEventListener('keyup', this.keyup);
this.showReminder();
}
cancel(type) {
document.removeEventListener('keydown', this.keydown);
document.removeEventListener('keyup', this.keyup);
const currentKeybinds = this.state.keybinds;
delete currentKeybinds[type];
this.setState({
keybinds: currentKeybinds,
cancelled: true
});
this.forceUpdate();
}
reset(type) {
const keybinds = this.state.keybinds;
keybinds[type] = '';
localStorage.setItem('keybinds', JSON.stringify(keybinds));
this.setState({
keybinds: JSON.parse(localStorage.getItem('keybinds')) || {},
cancelled: true
});
this.showReminder();
}
action(action, e) {
switch (action) {
case 'listen':
this.listen(e);
break;
case 'cancel':
this.cancel(e);
break;
case 'reset':
this.reset(e);
break;
default:
break;
}
}
render() {
return (
<>
<Header title={this.getMessage('modals.main.settings.sections.keybinds.title')} setting='keybindsEnabled' element='.other' />
<table className='keybind-table'>
<tbody>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.favourite')} state={this.state.keybinds} setting='favouriteBackground' action={(type, e) => this.action(type, e)}/></th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.maximise')} state={this.state.keybinds} setting='maximiseBackground' action={(type, e) => this.action(type, e)}/></th>
</tr>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.download')} state={this.state.keybinds} setting='downloadBackground' action={(type, e) => this.action(type, e)}/></th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.show_info')} state={this.state.keybinds} setting='showBackgroundInformation' action={(type, e) => this.action(type, e)}/></th>
</tr>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.show_info')} state={this.state.keybinds} setting='showBackgroundInformation' action={(type, e) => this.action(type, e)}/></th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quote.favourite')} state={this.state.keybinds} setting='favouriteQuote' action={(type, e) => this.action(type, e)}/></th>
</tr>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quote.copy')} state={this.state.keybinds} setting='copyQuote' action={(type, e) => this.action(type, e)}/></th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quote.tweet')} state={this.state.keybinds} setting='tweetQuote' action={(type, e) => this.action(type, e)}/></th>
</tr>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.notes.pin')} state={this.state.keybinds} setting='pinNotes' action={(type, e) => this.action(type, e)}/></th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.notes.copy')} state={this.state.keybinds} setting='copyNotes' action={(type, e) => this.action(type, e)}/></th>
</tr>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.search')} state={this.state.keybinds} setting='focusSearch' action={(type, e) => this.action(type, e)}/></th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quicklinks')} state={this.state.keybinds} setting='toggleQuicklinks' action={(type, e) => this.action(type, e)}/></th>
</tr>
<tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.modal')} state={this.state.keybinds} setting='toggleModal' action={(type, e) => this.action(type, e)}/></th>
</tr>
</tbody>
</table>
</>
);
}
}

View File

@@ -1,15 +1,18 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Radio from '../Radio';
const languages = require('../../../../../modules/languages.json');
const languages = require('modules/languages.json');
export default class LanguageSettings extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
export default class BackgroundSettings extends React.PureComponent {
constructor() {
super();
this.state = {
quoteLanguages: [{
name: window.language.modals.main.loading,
name: this.getMessage('modals.main.loading'),
value: 'loading'
}]
};
@@ -17,22 +20,22 @@ export default class BackgroundSettings extends React.PureComponent {
}
async getQuoteLanguages() {
const data = await (await fetch(window.constants.API_URL + '/quotes/languages', { signal: this.controller.signal })).json();
const data = await (await fetch(variables.constants.API_URL + '/quotes/languages', { signal: this.controller.signal })).json();
if (this.controller.signal.aborted === true) {
return;
}
let array = [];
data.forEach(item => {
array.push({
const quoteLanguages = [];
data.forEach((item) => {
quoteLanguages.push({
name: item,
value: item
});
});
this.setState({
quoteLanguages: array
quoteLanguages
});
}
@@ -40,11 +43,12 @@ export default class BackgroundSettings extends React.PureComponent {
if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
return this.setState({
quoteLanguages: [{
name: window.language.modals.main.marketplace.offline.description,
name: this.getMessage('modals.main.marketplace.offline.description'),
value: 'loading'
}]
});
}
this.getQuoteLanguages();
}
@@ -54,13 +58,11 @@ export default class BackgroundSettings extends React.PureComponent {
}
render() {
const language = window.language.modals.main.settings.sections.language;
return (
<>
<h2>{language.title}</h2>
<Radio name='language' options={languages} element='.language' />
<h3>{language.quote}</h3>
<h2>{this.getMessage('modals.main.settings.sections.language.title')}</h2>
<Radio name='language' options={languages} element='.other' />
<h3>{this.getMessage('modals.main.settings.sections.language.quote')}</h3>
<Radio name='quotelanguage' options={this.state.quoteLanguages} category='quote' />
</>
);

View File

@@ -0,0 +1,81 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { Cancel, Add } from '@mui/icons-material';
import { toast } from 'react-toastify';
import { TextField } from '@mui/material';
import Header from '../Header';
import EventBus from 'modules/helpers/eventbus';
export default class Message extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
constructor() {
super();
this.state = {
messages: JSON.parse(localStorage.getItem('messages')) || [''],
};
}
reset = () => {
localStorage.setItem('messages', '[""]');
this.setState({
messages: ['']
});
toast(this.getMessage(this.languagecode, 'toasts.reset'));
EventBus.dispatch('refresh', 'message');
}
modifyMessage(type, index) {
const messages = this.state.messages;
if (type === 'add') {
messages.push('');
} else {
messages.splice(index, 1);
}
this.setState({
messages
});
this.forceUpdate();
localStorage.setItem('messages', JSON.stringify(messages));
}
message(e, text, index) {
const result = (text === true) ? e.target.value : e.target.result;
const messages = this.state.messages;
messages[index] = result;
this.setState({
messages
});
this.forceUpdate();
localStorage.setItem('messages', JSON.stringify(messages));
document.querySelector('.reminder-info').style.display = 'block';
localStorage.setItem('showReminder', true);
}
render() {
return (
<>
<Header title={this.getMessage('modals.main.settings.sections.message.title')} setting='message' category='message' element='.message' zoomSetting='zoomMessage'/>
<p>{this.getMessage('modals.main.settings.sections.message.text')}</p>
<div className='data-buttons-row'>
<button onClick={() => this.modifyMessage('add')}>{this.getMessage('modals.main.settings.sections.message.add')} <Add/></button>
</div>
{this.state.messages.map((_url, index) => (
<div style={{ display: 'flex' }} key={index}>
<TextField value={this.state.messages[index]} onChange={(e) => this.message(e, true, index)} varient='outlined' />
{this.state.messages.length > 1 ? <button className='cleanButton' onClick={() => this.modifyMessage('remove', index)}>
<Cancel/>
</button> : null}
</div>
))}
<br/>
</>
);
}
}

View File

@@ -0,0 +1,34 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Checkbox from '../Checkbox';
import Dropdown from '../Dropdown';
import Slider from '../Slider';
import { values } from 'modules/helpers/settings/modals';
export default class Navbar extends PureComponent {
render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<>
<h2>{getMessage('modals.main.settings.sections.appearance.navbar.title')}</h2>
<Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.widget_zoom')} name='zoomNavbar' min='10' max='400' default='100' display='%' marks={values('zoom')} category='navbar' />
<Checkbox name='navbarHover' text={getMessage('modals.main.settings.sections.appearance.navbar.hover')} category='navbar'/>
<Checkbox name='notesEnabled' text={getMessage('modals.main.settings.sections.appearance.navbar.notes')} category='navbar' />
<Checkbox name='view' text={getMessage('modals.main.settings.sections.background.buttons.view')} category='navbar' />
<Checkbox name='favouriteEnabled' text={getMessage('modals.main.settings.sections.background.buttons.favourite')} category='navbar' />
<Dropdown label={getMessage('modals.main.settings.sections.appearance.navbar.refresh')} name='refresh' category='navbar'>
<option value='false'>{getMessage('modals.main.settings.sections.appearance.navbar.refresh_options.none')}</option>
<option value='background'>{getMessage('modals.main.settings.sections.background.title')}</option>
<option value='quote'>{getMessage('modals.main.settings.sections.quote.title')}</option>
<option value='quotebackground'>{getMessage('modals.main.settings.sections.quote.title')} + {getMessage('modals.main.settings.sections.background.title')}</option>
{/* before it was just a checkbox */}
<option value='true'>{getMessage('modals.main.settings.sections.appearance.navbar.refresh_options.page')}</option>
</Dropdown>
</>
);
}
}

View File

@@ -1,100 +1,94 @@
import React from 'react';
import EventBus from '../../../../../modules/helpers/eventbus';
import DragHandleIcon from '@material-ui/icons/DragIndicator';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { DragIndicator } from '@mui/icons-material';
import { sortableContainer, sortableElement } from 'react-sortable-hoc';
import { toast } from 'react-toastify';
const enabled = (setting) => {
switch (setting) {
case 'quicklinks':
return (localStorage.getItem('quicklinksenabled') === 'true');
default:
return (localStorage.getItem(setting) === 'true');
}
};
import EventBus from 'modules/helpers/eventbus';
const settings = window.language.modals.main.settings.sections;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
const widget_name = {
greeting: settings.greeting.title,
time: settings.time.title,
quicklinks: settings.quicklinks.title,
quote: settings.quote.title,
date: settings.time.date.title
greeting: getMessage('modals.main.settings.sections.greeting.title'),
time: getMessage('modals.main.settings.sections.time.title'),
quicklinks: getMessage('modals.main.settings.sections.quicklinks.title'),
quote: getMessage('modals.main.settings.sections.quote.title'),
date: getMessage('modals.main.settings.sections.date.title'),
message: getMessage('modals.main.settings.sections.message.title')
};
const SortableItem = sortableElement(({value}) => (
<li className='sortableitem' style={{ display: enabled(value) ? 'block' : 'none' }}>
<DragHandleIcon style={{'verticalAlign': 'middle'}} />
const SortableItem = sortableElement(({ value }) => (
<li className='sortableitem'>
<DragIndicator style={{ verticalAlign: 'middle' }} />
{widget_name[value]}
</li>
));
const SortableContainer = sortableContainer(({children}) => {
return <ul className='sortablecontainer'>{children}</ul>;
});
const SortableContainer = sortableContainer(({ children }) => (
<ul className='sortablecontainer'>{children}</ul>
));
export default class OrderSettings extends React.PureComponent {
export default class OrderSettings extends PureComponent {
constructor() {
super();
this.state = {
items: JSON.parse(localStorage.getItem('order'))
};
this.language = window.language.modals.main.settings;
}
// based on https://stackoverflow.com/a/48301905
arrayMove(array, oldIndex, newIndex) {
if (oldIndex === newIndex) {
return array;
}
const result = Array.from(array);
const [removed] = result.splice(oldIndex, 1);
result.splice(newIndex, 0, removed);
const newArray = [...array];
const target = newArray[oldIndex];
const inc = newIndex < oldIndex ? -1 : 1;
for (let i = oldIndex; i !== newIndex; i += inc) {
newArray[i] = newArray[i + inc];
}
newArray[newIndex] = target;
return newArray;
return result;
}
onSortEnd = ({oldIndex, newIndex}) => {
this.setState(({items}) => ({
items: this.arrayMove(items, oldIndex, newIndex)
}));
onSortEnd = ({ oldIndex, newIndex }) => {
this.setState({
items: this.arrayMove(this.state.items, oldIndex, newIndex)
});
}
reset = () => {
localStorage.setItem('order', JSON.stringify(['greeting', 'time', 'quicklinks', 'quote', 'date']));
localStorage.setItem('order', JSON.stringify(['greeting', 'time', 'quicklinks', 'quote', 'date', 'message']));
this.setState({
items: JSON.parse(localStorage.getItem('order'))
});
toast(window.language.toasts.reset);
toast(getMessage('toats.reset'));
}
enabled = (setting) => {
switch (setting) {
case 'quicklinks':
return (localStorage.getItem('quicklinksenabled') === 'true');
default:
return (localStorage.getItem(setting) === 'true');
}
}
componentDidUpdate() {
localStorage.setItem('order', JSON.stringify(this.state.items));
variables.stats.postEvent('setting', 'Widget order');
EventBus.dispatch('refresh', 'widgets');
}
render() {
return (
<>
<h2>{this.language.sections.order.title}</h2>
<span className='modalLink' onClick={this.reset}>{this.language.buttons.reset}</span>
<h2>{getMessage('modals.main.settings.sections.order.title')}</h2>
<span className='modalLink' onClick={this.reset}>{getMessage('modals.main.settings.buttons.reset')}</span>
<SortableContainer onSortEnd={this.onSortEnd} lockAxis='y' lockToContainerEdges disableAutoscroll>
{this.state.items.map((value, index) => (
<SortableItem key={`item-${value}`} index={index} value={value} />
))}
{this.state.items.map((value, index) => {
if (!this.enabled(value)) {
return null;
}
return (
<SortableItem key={`item-${value}`} index={index} value={value} />
);
})}
</SortableContainer>
</>
);

View File

@@ -1,17 +1,20 @@
import React from 'react';
import variables from 'modules/variables';
import { useState } from 'react';
import Switch from '../Switch';
import Header from '../Header';
import Checkbox from '../Checkbox';
export default function QuickLinks() {
const language = window.language.modals.main.settings.sections.quicklinks;
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
const [textOnly, setTextOnly] = useState(localStorage.getItem('quicklinksText') === 'true');
return (
<>
<h2>{language.title}</h2>
<Switch name='quicklinksenabled' text={window.language.modals.main.settings.enabled} category='quicklinks' element='.quicklinks-container' />
<Checkbox name='quicklinksnewtab' text={language.open_new} category='quicklinks' />
<Checkbox name='quicklinkstooltip' text={language.tooltip} category='quicklinks' />
<Header title={getMessage('modals.main.settings.sections.quicklinks.title')} setting='quicklinksenabled' category='quicklinks' element='.quicklinks-container' zoomSetting='zoomQuicklinks'/>
<Checkbox name='quicklinksText' text={getMessage('modals.main.settings.sections.quicklinks.text_only')} category='quicklinks' onChange={(value) => setTextOnly(value)}/>
<Checkbox name='quicklinksddgProxy' text={getMessage('modals.main.settings.sections.background.ddg_image_proxy')} category='quicklinks' disabled={textOnly}/>
<Checkbox name='quicklinksnewtab' text={getMessage('modals.main.settings.sections.quicklinks.open_new')} category='quicklinks'/>
<Checkbox name='quicklinkstooltip' text={getMessage('modals.main.settings.sections.quicklinks.tooltip')} category='quicklinks' disabled={textOnly}/>
</>
);
}

View File

@@ -1,24 +1,139 @@
import React from 'react';
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { Cancel, Add } from '@mui/icons-material';
import { TextField } from '@mui/material';
import Header from '../Header';
import Checkbox from '../Checkbox';
import Text from '../Text';
import Switch from '../Switch';
import Dropdown from '../Dropdown';
export default function QuoteSettings() {
const { quote } = window.language.modals.main.settings.sections;
export default class QuoteSettings extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return (
<>
<h2>{quote.title}</h2>
<Switch name='quote' text={window.language.modals.main.settings.enabled} category='quote' element='.quotediv' />
<Checkbox name='authorLink' text={quote.author_link} element='.other' />
<Text title={quote.custom} name='customQuote' element='.other' />
<Text title={quote.custom_author} name='customQuoteAuthor' element='.other'/>
constructor() {
super();
this.state = {
quoteType: localStorage.getItem('quoteType') || 'api',
customQuote: this.getCustom()
};
}
<h3>{quote.buttons.title}</h3>
<Checkbox name='copyButton' text={quote.buttons.copy} category='quote'/>
<Checkbox name='tweetButton' text={quote.buttons.tweet} category='quote'/>
<Checkbox name='favouriteQuoteEnabled' text={quote.buttons.favourite} category='quote'/>
</>
);
}
marketplaceType = () => {
if (localStorage.getItem('quote_packs')) {
return <option value='quote_pack'>{this.getMessage('modals.main.navbar.marketplace')}</option>;
}
}
resetCustom = () => {
localStorage.setItem('customQuote', '[{"quote": "", "author": ""}]');
this.setState({
customQuote: [{
quote: '',
author: ''
}]
});
toast(this.getMessage('toasts.reset'));
EventBus.dispatch('refresh', 'background');
}
customQuote(e, text, index, type) {
const result = (text === true) ? e.target.value : e.target.result;
const customQuote = this.state.customQuote;
customQuote[index][type] = result;
this.setState({
customQuote
});
this.forceUpdate();
localStorage.setItem('customQuote', JSON.stringify(customQuote));
document.querySelector('.reminder-info').style.display = 'block';
localStorage.setItem('showReminder', true);
}
modifyCustomQuote(type, index) {
const customQuote = this.state.customQuote;
if (type === 'add') {
customQuote.push({
quote: '',
author: ''
});
} else {
customQuote.splice(index, 1);
}
this.setState({
customQuote
});
this.forceUpdate();
localStorage.setItem('customQuote', JSON.stringify(customQuote));
}
getCustom() {
let data = JSON.parse(localStorage.getItem('customQuote'));
if (data === null) {
data = [{
quote: localStorage.getItem('customQuote') || '',
author: localStorage.getItem('customQuoteAuthor') || ''
}];
}
return data;
}
render() {
let customSettings;
if (this.state.quoteType === 'custom') {
customSettings = (
<>
<p>{this.getMessage('modals.main.settings.sections.quote.custom')} <span className='modalLink' onClick={this.resetCustom}>{this.getMessage('modals.main.settings.buttons.reset')}</span></p>
<div className='data-buttons-row'>
<button onClick={() => this.modifyCustomQuote('add')}>{this.getMessage('modals.main.settings.sections.quote.add')} <Add/></button>
</div>
{this.state.customQuote.map((_url, index) => (
<div style={{ display: 'flex' }} key={index}>
<TextField value={this.state.customQuote[index].quote} placeholder='Quote' onChange={(e) => this.customQuote(e, true, index, 'quote')} varient='outlined' style={{ marginRight: '10px' }} />
<TextField value={this.state.customQuote[index].author} placeholder='Author' onChange={(e) => this.customQuote(e, true, index, 'author')} varient='outlined' />
{this.state.customQuote.length > 1 ? <button className='cleanButton' onClick={() => this.modifyCustomQuote('remove', index)} style={{ marginBottom: '-14px' }}>
<Cancel/>
</button> : null}
</div>
))}
</>
);
} else {
// api
customSettings = (
<>
<Dropdown label={this.getMessage('modals.main.settings.sections.background.interval.title')} name='quotechange'>
<option value='refresh'>{this.getMessage('tabname')}</option>
<option value='60000'>{this.getMessage('modals.main.settings.sections.background.interval.minute')}</option>
<option value='1800000'>{this.getMessage('modals.main.settings.sections.background.interval.half_hour')}</option>
<option value='3600000'>{this.getMessage('modals.main.settings.sections.background.interval.hour')}</option>
<option value='86400000'>{this.getMessage('modals.main.settings.sections.background.interval.day')}</option>
<option value='604800000'>{this.getMessage('widgets.date.week')}</option>
<option value='2628000000'>{this.getMessage('modals.main.settings.sections.background.interval.month')}</option>
</Dropdown>
</>
);
}
return (
<>
<Header title={this.getMessage('modals.main.settings.sections.quote.title')} setting='quote' category='quote' element='.quotediv' zoomSetting='zoomQuote'/>
<Checkbox name='authorLink' text={this.getMessage('modals.main.settings.sections.quote.author_link')} element='.other' />
<Dropdown label={this.getMessage('modals.main.settings.sections.background.type.title')} name='quoteType' onChange={(value) => this.setState({ quoteType: value })} category='quote'>
{this.marketplaceType()}
<option value='api'>{this.getMessage('modals.main.settings.sections.background.type.api')}</option>
<option value='custom'>{this.getMessage('modals.main.settings.sections.quote.custom')}</option>
</Dropdown>
{customSettings}
<h3>{this.getMessage('modals.main.settings.sections.quote.buttons.title')}</h3>
<Checkbox name='copyButton' text={this.getMessage('modals.main.settings.sections.quote.buttons.copy')} category='quote'/>
<Checkbox name='tweetButton' text={this.getMessage('modals.main.settings.sections.quote.buttons.tweet')} category='quote'/>
<Checkbox name='favouriteQuoteEnabled' text={this.getMessage('modals.main.settings.sections.quote.buttons.favourite')} category='quote'/>
</>
);
}
}

Some files were not shown because too many files have changed in this diff Show More