Compare commits

..

539 Commits
7.1.2 ... 8.0

Author SHA1 Message Date
Arif Budiman
67b453d413 Translated using Weblate (Indonesian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/id/
2026-04-23 13:10:09 +00:00
Arif Budiman
05cd1f70d3 Translated using Weblate (Indonesian)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/id/
2026-04-23 13:10:06 +00:00
Arif Budiman
c0ae06e766 Translated using Weblate (Indonesian)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/id/
2026-04-23 13:10:04 +00:00
Arif Budiman
6edb7be310 Translated using Weblate (Indonesian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/id/
2026-04-23 13:10:02 +00:00
Arif Budiman
191624df37 Translated using Weblate (Indonesian)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/id/
2026-04-23 13:10:00 +00:00
Arif Budiman
7a179fe511 Translated using Weblate (Indonesian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/id/
2026-04-23 13:09:57 +00:00
飞舞
8f087409d5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 58.3% (14 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/zh_Hans/
2026-04-04 23:09:55 +02:00
飞舞
37f5b88049 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 84.6% (33 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/zh_Hans/
2026-04-04 23:09:54 +02:00
飞舞
1b9e48d9ef Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 65.4% (205 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/zh_Hans/
2026-04-04 23:09:52 +02:00
Weblate Translation Memory
d646fad4f6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 45.6% (21 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/zh_Hans/
2026-04-04 23:09:51 +02:00
飞舞
2075aec8f7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 45.6% (21 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/zh_Hans/
2026-04-04 23:09:50 +02:00
飞舞
6c735caff0 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 65.2% (15 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/zh_Hans/
2026-04-04 23:09:48 +02:00
Gustavo J. Lopez
7bc4905536 Translated using Weblate (Spanish (Latin America))
Currently translated at 32.6% (15 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/es_419/
2026-03-10 14:09:49 +00:00
LibreTranslate
7a717fb3d1 Translated using Weblate (Korean)
Currently translated at 97.4% (38 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/ko/
2026-02-21 12:10:31 +01:00
Deesse ̨
0ba4ca03e1 Translated using Weblate (Korean)
Currently translated at 97.4% (38 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/ko/
2026-02-21 12:10:30 +01:00
Deesse ̨
63b2898a53 Translated using Weblate (Korean)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/ko/
2026-02-21 12:10:28 +01:00
Daniel Wiik
69303b389c Translated using Weblate (Swedish)
Currently translated at 23.0% (9 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/sv/
2026-02-21 12:10:26 +01:00
Daniel Wiik
67b18de8bd Translated using Weblate (Swedish)
Currently translated at 11.2% (9 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/sv/
2026-02-21 12:10:24 +01:00
Daniel Wiik
ee10b96dc0 Translated using Weblate (Swedish)
Currently translated at 33.3% (8 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/sv/
2026-02-21 12:10:22 +01:00
Daniel Wiik
45ddc7642b Translated using Weblate (Swedish)
Currently translated at 39.1% (9 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/sv/
2026-02-21 12:10:19 +01:00
Deesse ̨
26f18b3667 Translated using Weblate (Korean)
Currently translated at 95.8% (23 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/ko/
2026-02-21 12:10:17 +01:00
Daniel Wiik
5f83589ba7 Translated using Weblate (Swedish)
Currently translated at 19.5% (9 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/sv/
2026-02-21 12:10:13 +01:00
LibreTranslate
1d9df10d4e Translated using Weblate (Korean)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ko/
2026-02-21 12:10:12 +01:00
Deesse ̨
03488fea78 Translated using Weblate (Korean)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ko/
2026-02-21 12:10:09 +01:00
LibreTranslate
0295094d87 Translated using Weblate (Korean)
Currently translated at 96.4% (302 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/ko/
2026-02-21 12:10:05 +01:00
Deesse ̨
b5e3151cce Translated using Weblate (Korean)
Currently translated at 96.4% (302 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/ko/
2026-02-21 12:10:04 +01:00
LibreTranslate
1148d27c4a Translated using Weblate (Korean)
Currently translated at 96.4% (302 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/ko/
2026-02-21 12:09:53 +01:00
Daniel Wiik
79c54e4074 Translated using Weblate (Swedish)
Currently translated at 2.8% (9 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/sv/
2026-02-21 12:09:51 +01:00
Deesse ̨
e58a0d6c99 Translated using Weblate (Korean)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/ko/
2026-02-21 12:09:48 +01:00
Daniel Wiik
f4f4cf0fad Translated using Weblate (Swedish)
Currently translated at 17.3% (8 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/sv/
2026-02-16 01:09:55 +01:00
Daniel Wiik
9692363c1d Translated using Weblate (Swedish)
Currently translated at 20.5% (8 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/sv/
2026-02-16 01:09:54 +01:00
Daniel Wiik
5e23df6040 Translated using Weblate (Swedish)
Currently translated at 2.2% (7 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/sv/
2026-02-16 01:09:52 +01:00
Daniel Wiik
0a5e4abec2 Translated using Weblate (Swedish)
Currently translated at 34.7% (8 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/sv/
2026-02-16 01:09:50 +01:00
Daniel Wiik
4474eff9e6 Translated using Weblate (Swedish)
Currently translated at 10.0% (8 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/sv/
2026-02-16 01:09:48 +01:00
Daniel Wiik
d930ed2f59 Translated using Weblate (Swedish)
Currently translated at 29.1% (7 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/sv/
2026-02-16 01:09:46 +01:00
Academion
6bd82985b7 Translated using Weblate (German)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/de/
2026-02-10 09:09:45 +01:00
Kai A.
1b6d6a45af Translated using Weblate (German)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/de/
2026-02-10 09:09:44 +01:00
Kang
2fafed94d2 Translated using Weblate (Korean)
Currently translated at 58.7% (47 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ko/
2026-01-14 19:01:48 +01:00
Kang
4426b54f65 Added translation using Weblate (Korean) 2026-01-14 06:44:53 +01:00
Kang
f0828a87d9 Added translation using Weblate (Korean) 2026-01-14 06:44:48 +01:00
Kang
bd754fcb69 Added translation using Weblate (Korean) 2026-01-14 06:44:43 +01:00
Kang
ce71191856 Added translation using Weblate (Korean) 2026-01-14 06:44:39 +01:00
Kang
4f1165d59b Added translation using Weblate (Korean) 2026-01-14 06:44:36 +01:00
Kang
0512993ba8 Added translation using Weblate (Korean) 2026-01-14 06:44:24 +01:00
Weblate Translation Memory
d61246086e Translated using Weblate (French)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2026-01-04 06:01:51 +00:00
LibreTranslate
328e47bfea Translated using Weblate (French)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2026-01-04 06:01:50 +00:00
Pose marto
e8579eb1dd Translated using Weblate (French)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2026-01-04 06:01:49 +00:00
Pose marto
531a72a8e8 Translated using Weblate (French)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2026-01-04 06:01:47 +00:00
Seyed Amir MirMohammadi
0f3915f655 Translated using Weblate (Persian)
Currently translated at 7.6% (3 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/fa/
2026-01-03 17:58:51 +01:00
Seyed Amir MirMohammadi
dd3ba29a5c Translated using Weblate (Persian)
Currently translated at 17.3% (4 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/fa/
2026-01-03 17:58:50 +01:00
Seyed Amir MirMohammadi
8348aec931 Translated using Weblate (Persian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fa/
2026-01-03 17:58:50 +01:00
Seyed Amir MirMohammadi
ee1f3bf3eb Translated using Weblate (Persian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/fa/
2026-01-03 17:58:48 +01:00
Seyed Amir MirMohammadi
732091c86b Translated using Weblate (Persian)
Currently translated at 16.6% (4 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/fa/
2026-01-03 17:58:46 +01:00
Seyed Amir MirMohammadi
8f65ebec5a Translated using Weblate (Persian)
Currently translated at 0.9% (3 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fa/
2026-01-03 17:58:46 +01:00
LibreTranslate
2c56bfeb87 Translated using Weblate (French)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2026-01-01 22:01:50 +00:00
Weblate Translation Memory
c77226dcb0 Translated using Weblate (French)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2026-01-01 22:01:49 +00:00
Pose marto
044d44ebe1 Translated using Weblate (French)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2026-01-01 22:01:48 +00:00
Doen1el
5df62b8c7e Translated using Weblate (German)
Currently translated at 98.7% (79 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/de/
2026-01-01 03:01:47 +01:00
pooya mokhtari
2196931cfa Translated using Weblate (Persian (Old))
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/peo/
2025-12-28 23:00:20 +01:00
Languages add-on
42032bb889 Added translation using Weblate (Persian (Old)) 2025-12-28 10:54:25 +01:00
Languages add-on
a4c3f96528 Added translation using Weblate (Persian (Old)) 2025-12-28 10:54:21 +01:00
Languages add-on
0636c0a567 Added translation using Weblate (Persian (Old)) 2025-12-28 10:54:19 +01:00
Languages add-on
f35bdfa7f4 Added translation using Weblate (Persian (Old)) 2025-12-28 10:54:17 +01:00
Languages add-on
56271f6fc4 Added translation using Weblate (Persian (Old)) 2025-12-28 10:54:15 +01:00
Languages add-on
69b4c8bb27 Added translation using Weblate (Persian (Old)) 2025-12-28 10:54:11 +01:00
Pose marto
775717b297 Translated using Weblate (French)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/fr/
2025-12-25 22:00:33 +00:00
Pose marto
481f116b28 Translated using Weblate (French)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/fr/
2025-12-25 22:00:31 +00:00
LibreTranslate
eb6e8d261f Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:30 +00:00
Weblate Translation Memory
5b43037927 Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:29 +00:00
Pose marto
2a3d1fe56d Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:28 +00:00
LibreTranslate
1424d5856e Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:26 +00:00
LibreTranslate
e94cc8abe0 Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:24 +00:00
Weblate Translation Memory
80198d0d5d Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:23 +00:00
LibreTranslate
541f1b4727 Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:22 +00:00
LibreTranslate
5dfdbc0aa3 Translated using Weblate (French)
Currently translated at 82.4% (258 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 22:00:20 +00:00
LibreTranslate
c238d687e9 Translated using Weblate (French)
Currently translated at 56.2% (176 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 04:00:20 +01:00
Pose marto
b4d33509bf Translated using Weblate (French)
Currently translated at 56.2% (176 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 04:00:20 +01:00
Weblate Translation Memory
5d9f0a70a2 Translated using Weblate (French)
Currently translated at 56.2% (176 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-12-25 04:00:20 +01:00
Pose marto
7887357cb9 Translated using Weblate (French)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/fr/
2025-12-24 07:00:21 +01:00
Pose marto
30b7218d43 Translated using Weblate (French)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/fr/
2025-12-24 07:00:21 +01:00
LibreTranslate
e65c8c6e38 Translated using Weblate (French)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/fr/
2025-12-24 07:00:20 +01:00
LibreTranslate
db16732bd0 Translated using Weblate (French)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/fr/
2025-12-24 07:00:20 +01:00
Pose marto
daed931602 Translated using Weblate (French)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-12-23 06:00:19 +00:00
Saúl Palacios
40131ad9c8 Translated using Weblate (Spanish)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/es/
2025-12-13 06:00:21 +00:00
Saúl Palacios
c54b33d95d Translated using Weblate (Spanish)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/es/
2025-12-13 06:00:20 +00:00
Saúl Palacios
57b158e614 Translated using Weblate (Spanish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/es/
2025-12-13 06:00:19 +00:00
Anthony Cyndora
416a81ef3b Translated using Weblate (French)
Currently translated at 98.7% (79 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-11-30 10:00:20 +01:00
Munch Rémi
bd6e046155 Translated using Weblate (French)
Currently translated at 92.3% (36 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/fr/
2025-11-28 22:00:25 +00:00
Munch Rémi
5790bdfb40 Translated using Weblate (French)
Currently translated at 91.3% (42 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/fr/
2025-11-28 22:00:19 +00:00
Munch Rémi
c98aeb8c60 Translated using Weblate (French)
Currently translated at 93.7% (75 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-11-28 05:01:10 +00:00
Munch Rémi
3ac567af50 Translated using Weblate (French)
Currently translated at 47.2% (148 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-11-28 05:00:49 +00:00
lxy
43f8d564e6 Translated using Weblate (English (United States))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/en_US/
2025-11-27 05:00:22 +00:00
LibreTranslate
b6fe0ad393 Translated using Weblate (Spanish (Latin America))
Currently translated at 94.8% (37 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/es_419/
2025-11-02 13:52:44 +00:00
Alejandro
783d7dba1b Translated using Weblate (Spanish (Latin America))
Currently translated at 94.8% (37 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/es_419/
2025-11-02 13:52:42 +00:00
LibreTranslate
7d44727626 Translated using Weblate (Spanish (Latin America))
Currently translated at 94.8% (37 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/es_419/
2025-11-02 13:52:33 +00:00
resu-xuniL
a4c5ed492c Translated using Weblate (French)
Currently translated at 78.7% (63 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-10-26 12:02:42 +01:00
Weblate Translation Memory
1cab0c9515 Translated using Weblate (Spanish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/es/
2025-10-23 10:02:57 +00:00
LibreTranslate
81ee2f52de Translated using Weblate (Spanish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/es/
2025-10-23 10:02:55 +00:00
Saúl Palacios
57da011daa Translated using Weblate (Spanish)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/es/
2025-10-23 10:02:54 +00:00
Saúl Palacios
d9da22c043 Translated using Weblate (Spanish)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/es/
2025-10-23 10:02:44 +00:00
LibreTranslate
2126bb1fe7 Translated using Weblate (Spanish)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/es/
2025-10-23 10:02:42 +00:00
Kağan Can Şit
31d43ff315 Translated using Weblate (Turkish)
Currently translated at 100.0% (312 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/tr/
2025-10-17 07:07:52 +02:00
Walter Pagani
33dbbc0476 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/es_419/
2025-09-17 04:52:00 +02:00
LibreTranslate
c6087c3c37 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2025-09-17 04:52:00 +02:00
Walter Pagani
46090e430c Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2025-09-17 04:52:00 +02:00
Louis
0dd5287acf Translated using Weblate (French)
Currently translated at 28.2% (11 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/fr/
2025-08-29 09:01:57 +02:00
Louis
47167b9709 Translated using Weblate (French)
Currently translated at 78.7% (63 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-08-29 09:01:56 +02:00
Louis
5bd567deb9 Translated using Weblate (French)
Currently translated at 38.6% (121 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/fr/
2025-08-27 23:02:12 +00:00
Louis
a875f3cfb1 Translated using Weblate (French)
Currently translated at 32.6% (15 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/fr/
2025-08-27 23:02:11 +00:00
Louis
5b2e0f7828 Translated using Weblate (French)
Currently translated at 23.0% (9 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/fr/
2025-08-27 23:02:09 +00:00
Louis
6eb2bedcb3 Translated using Weblate (French)
Currently translated at 34.7% (8 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/fr/
2025-08-27 23:02:08 +00:00
Louis
3f503d66c3 Translated using Weblate (French)
Currently translated at 62.5% (15 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/fr/
2025-08-27 23:02:06 +00:00
Louis
f5437546ec Translated using Weblate (French)
Currently translated at 76.2% (61 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-08-27 23:02:04 +00:00
NightOwlEyes
a9085d9fbf Translated using Weblate (Vietnamese)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/vi/
2025-08-25 18:01:53 +00:00
Максим Горпиніч
bbab060ef7 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/uk/
2025-08-23 06:02:15 +00:00
Максим Горпиніч
44670d9c79 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/uk/
2025-08-23 06:02:14 +00:00
LibreTranslate
0ac2043cff Translated using Weblate (Ukrainian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/uk/
2025-08-23 06:02:12 +00:00
Данил Поляков
6587dbec86 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/uk/
2025-08-23 06:02:11 +00:00
Максим Горпиніч
b6a7a96d18 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/uk/
2025-08-23 06:02:10 +00:00
Максим Горпиніч
56ee9d2f37 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/uk/
2025-08-23 06:02:08 +00:00
Данил Поляков
b482013b25 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/uk/
2025-08-23 06:02:07 +00:00
Максим Горпиніч
87d88ddfb7 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/uk/
2025-08-23 06:02:06 +00:00
LibreTranslate
3f080cb8f9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/uk/
2025-08-23 06:02:05 +00:00
Максим Горпиніч
17c8a2dbe2 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/uk/
2025-08-23 06:02:04 +00:00
Максим Горпиніч
58c4a86f39 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/uk/
2025-08-23 06:02:02 +00:00
Данил Поляков
e43b3ac766 Translated using Weblate (Ukrainian)
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/uk/
2025-08-21 14:01:57 +00:00
Languages add-on
1e341b4a51 Added translation using Weblate (Ukrainian) 2025-08-21 01:25:54 +00:00
Languages add-on
0941555d68 Added translation using Weblate (Ukrainian) 2025-08-21 01:25:50 +00:00
Languages add-on
f67f642341 Added translation using Weblate (Ukrainian) 2025-08-21 01:25:49 +00:00
Languages add-on
2eb936b853 Added translation using Weblate (Ukrainian) 2025-08-21 01:25:47 +00:00
Languages add-on
908d3ea26a Added translation using Weblate (Ukrainian) 2025-08-21 01:25:45 +00:00
Languages add-on
f78700e5b8 Added translation using Weblate (Ukrainian) 2025-08-21 01:25:39 +00:00
John Joseph A. Gatchalian
8f1bdd3234 Translated using Weblate (English (United States))
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/en_US/
2025-08-21 01:25:38 +00:00
Languages add-on
6c033c72eb Added translation using Weblate (Arabic (Egyptian)) 2025-07-31 14:00:33 +02:00
Languages add-on
8bc01b98e0 Added translation using Weblate (Arabic (Egyptian)) 2025-07-31 14:00:28 +02:00
Languages add-on
ed66a65757 Added translation using Weblate (Arabic (Egyptian)) 2025-07-31 14:00:21 +02:00
Languages add-on
62c4b0ccc8 Added translation using Weblate (Arabic (Egyptian)) 2025-07-31 14:00:18 +02:00
Languages add-on
d27e0722d2 Added translation using Weblate (Arabic (Egyptian)) 2025-07-31 14:00:16 +02:00
Languages add-on
b7bb5ea493 Added translation using Weblate (Arabic (Egyptian)) 2025-07-31 14:00:10 +02:00
michte
3f1b749537 Translated using Weblate (Dutch)
Currently translated at 95.0% (76 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/nl/
2025-07-25 00:06:00 +02:00
Languages add-on
85e3163bd9 Added translation using Weblate (Hungarian) 2025-07-20 14:42:53 +00:00
Languages add-on
0287a6c100 Added translation using Weblate (Hungarian) 2025-07-20 14:42:48 +00:00
Languages add-on
dfd69ddc28 Added translation using Weblate (Hungarian) 2025-07-20 14:42:46 +00:00
Languages add-on
2d87e6f731 Added translation using Weblate (Hungarian) 2025-07-20 14:42:43 +00:00
Languages add-on
e373a7ec62 Added translation using Weblate (Hungarian) 2025-07-20 14:42:40 +00:00
Languages add-on
05c5306343 Added translation using Weblate (Hungarian) 2025-07-20 14:42:34 +00:00
LibreTranslate
0573851fd3 Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
Chris Batris
ea6891fd92 Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
e94581ffa8 Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
Chris Batris
324dcc5f6c Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
Chris Batris
65ad316813 Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
d4f1469d41 Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
f83ad3f3af Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
1566b1714a Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
ae739fc218 Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
f9a094a10d Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
LibreTranslate
6f3cfb812a Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:22 +02:00
Chris Batris
e12b442e9a Translated using Weblate (Greek)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/el/
2025-07-17 07:33:21 +02:00
Maydo Al-Dosery
658967a86b Translated using Weblate (English (United States))
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/en_US/
2025-07-16 10:02:00 +02:00
Maydo Al-Dosery
9cc9b075a9 Translated using Weblate (English (United States))
Currently translated at 4.3% (1 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/en_US/
2025-07-16 10:01:58 +02:00
Weblate Translation Memory
df7598b640 Translated using Weblate (English (United States))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/en_US/
2025-07-16 10:01:55 +02:00
Languages add-on
427bc7bc73 Added translation using Weblate (Greek) 2025-06-28 23:55:02 +02:00
Languages add-on
368eb7727d Added translation using Weblate (Greek) 2025-06-28 23:54:58 +02:00
Languages add-on
d16c028bed Added translation using Weblate (Greek) 2025-06-28 23:54:57 +02:00
Languages add-on
873d52e368 Added translation using Weblate (Greek) 2025-06-28 23:54:55 +02:00
Languages add-on
a90a10699b Added translation using Weblate (Greek) 2025-06-28 23:54:54 +02:00
Languages add-on
daa6fc9354 Added translation using Weblate (Greek) 2025-06-28 23:54:51 +02:00
Kağan Can Şit
bc4e31abc9 Translated using Weblate (Turkish)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/tr/
2025-06-15 08:02:01 +00:00
Kağan Can Şit
565c95d72d Translated using Weblate (Turkish)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/tr/
2025-06-15 08:02:00 +00:00
WEBBAB
84839123b9 Translated using Weblate (Swedish)
Currently translated at 0.3% (1 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/sv/
2025-06-01 10:27:04 +02:00
LibreTranslate
1a180c535d Translated using Weblate (Swedish)
Currently translated at 4.1% (1 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/sv/
2025-06-01 10:27:04 +02:00
WEBBAB
8e0c13abdd Translated using Weblate (Swedish)
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/sv/
2025-06-01 10:27:04 +02:00
Languages add-on
000ffc4f70 Added translation using Weblate (Swedish) 2025-06-01 08:14:16 +00:00
Languages add-on
639e70391d Added translation using Weblate (Swedish) 2025-06-01 08:14:12 +00:00
Languages add-on
68bf8bfe12 Added translation using Weblate (Swedish) 2025-06-01 08:14:09 +00:00
Languages add-on
4b72a844e9 Added translation using Weblate (Swedish) 2025-06-01 08:14:07 +00:00
Languages add-on
7920ad3733 Added translation using Weblate (Swedish) 2025-06-01 08:14:04 +00:00
Languages add-on
2737b75d5b Added translation using Weblate (Swedish) 2025-06-01 08:13:59 +00:00
Dwynx
2514119313 Translated using Weblate (French)
Currently translated at 58.7% (47 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2025-05-13 12:02:16 +02:00
abdelbasset jabrane
303b7e0eb3 Translated using Weblate (Arabic)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/ar/
2025-05-10 08:01:56 +02:00
abdelbasset jabrane
4c98871006 Translated using Weblate (Arabic)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/ar/
2025-05-10 08:01:55 +02:00
abdelbasset jabrane
5c1bdfb798 Translated using Weblate (Arabic)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/ar/
2025-05-10 08:01:50 +02:00
abdelbasset jabrane
f5a7234ff6 Translated using Weblate (Arabic)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ar/
2025-05-10 08:01:49 +02:00
abdelbasset jabrane
f7a3d6bf96 Translated using Weblate (Arabic)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/ar/
2025-05-10 08:01:48 +02:00
abdelbasset jabrane
8701aea3a5 Translated using Weblate (Arabic)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/ar/
2025-05-10 08:01:47 +02:00
LibreTranslate
5b09c5d195 Translated using Weblate (Japanese)
Currently translated at 45.0% (36 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ja/
2025-04-04 02:10:28 +02:00
Tachibana Saza
9392008873 Translated using Weblate (Japanese)
Currently translated at 45.0% (36 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ja/
2025-04-04 02:10:28 +02:00
Languages add-on
f617271496 Added translation using Weblate (Arabic) 2025-03-14 00:46:52 +01:00
Languages add-on
cec3b82c07 Added translation using Weblate (Arabic) 2025-03-14 00:46:48 +01:00
Languages add-on
f6764f1d85 Added translation using Weblate (Arabic) 2025-03-14 00:46:46 +01:00
Languages add-on
f38011faac Added translation using Weblate (Arabic) 2025-03-13 23:44:32 +00:00
Languages add-on
8666b8d5ef Added translation using Weblate (Arabic) 2025-03-13 23:44:29 +00:00
Languages add-on
1e7b665e3f Added translation using Weblate (Arabic) 2025-03-13 23:44:26 +00:00
LibreTranslate
1b1eb70b39 Translated using Weblate (German)
Currently translated at 95.0% (76 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/de/
2025-01-31 19:05:55 +01:00
Kai A
4b9460370d Translated using Weblate (German)
Currently translated at 95.0% (76 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/de/
2025-01-31 19:05:55 +01:00
Weblate Translation Memory
8ec7d86e79 Translated using Weblate (German)
Currently translated at 95.0% (76 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/de/
2025-01-31 19:05:55 +01:00
Nguyen Duy Thanh
e3878c3f76 Translated using Weblate (Vietnamese)
Currently translated at 16.2% (13 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/vi/
2025-01-26 07:02:26 +01:00
தமிழ்நேரம்
ce973295f4 Translated using Weblate (Tamil)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/ta/
2025-01-19 21:00:49 +01:00
தமிழ்நேரம்
a82e77524f Translated using Weblate (Tamil)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ta/
2025-01-19 21:00:48 +01:00
தமிழ்நேரம்
baf184771b Translated using Weblate (Tamil)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/ta/
2025-01-19 21:00:46 +01:00
தமிழ்நேரம்
564bf8f8a6 Translated using Weblate (Tamil)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/ta/
2025-01-19 21:00:45 +01:00
Languages add-on
c5476d9dde Added translation using Weblate (Tamil) 2025-01-19 07:09:52 +01:00
Languages add-on
d9f363ec4b Added translation using Weblate (Tamil) 2025-01-19 05:50:19 +00:00
Languages add-on
2d3da9e9a7 Added translation using Weblate (Tamil) 2025-01-19 06:49:04 +01:00
Languages add-on
5b30600d8b Added translation using Weblate (Tamil) 2025-01-19 06:48:39 +01:00
Languages add-on
4f34d4ccbd Added translation using Weblate (Tamil) 2025-01-19 06:48:22 +01:00
Languages add-on
1261893130 Added translation using Weblate (Tamil) 2025-01-19 06:48:05 +01:00
Languages add-on
fdcbee07fa Added translation using Weblate (Japanese) 2025-01-05 07:04:46 +00:00
Languages add-on
93efa65e27 Added translation using Weblate (Japanese) 2025-01-05 07:04:33 +00:00
Languages add-on
1ddc81cd65 Added translation using Weblate (Japanese) 2025-01-05 07:04:17 +00:00
Languages add-on
64015da127 Added translation using Weblate (Japanese) 2025-01-05 07:03:13 +00:00
Languages add-on
cbd01abef5 Added translation using Weblate (Japanese) 2025-01-05 07:02:30 +00:00
Languages add-on
3fdf85234d Added translation using Weblate (Japanese) 2025-01-05 07:02:15 +00:00
Anthony Romero
e0ad97e96d Translated using Weblate (Spanish (Latin America))
Currently translated at 86.2% (69 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-12-30 21:00:59 +00:00
David Ralph
18519d932c feat(tests): start work on component testing (wip) 2024-12-27 21:09:24 +00:00
David Ralph
bd60088dc8 chore(tests): finish layout for welcome, add a few more tests and add placeholders for other features 2024-12-27 20:46:00 +00:00
David Ralph
6c9f2dd807 feat(tests): add cypress e2e 2024-12-27 20:24:42 +00:00
alexsparkes
d78a3a93b8 style(dropdown): style improvements 2024-12-22 21:14:05 +00:00
alexsparkes
36313c0127 fix(slider): visual performance issues 2024-12-22 20:55:25 +00:00
alexsparkes
75ae3a22cb feat(slider): click to edit value 2024-12-22 19:11:05 +00:00
alexsparkes
4a040acb62 fixIindexed db)L rename db 2024-12-19 17:23:09 +00:00
alexsparkes
f439ef7f10 feat(achievements): implement IndexedDB for achievement storage and retrieval 2024-12-19 17:00:36 +00:00
alexsparkes
59205cf9bf feat(stats): local sessions 2024-12-18 22:33:28 +00:00
alexsparkes
85a9150be1 refactor(quote): functional component 2024-12-17 21:14:46 +00:00
alexsparkes
94b33388b2 fix(search): Add preview to options 2024-12-17 20:31:36 +00:00
alexsparkes
15f1e523b4 feat(slider): add editable value display and enhance reset button functionality 2024-12-16 22:24:35 +00:00
alexsparkes
45959408c5 feat(greeting): add preview 2024-12-16 22:06:10 +00:00
alexsparkes
e7994d2644 feat(textarea): implement TextareaAutosize component and update imports across the application 2024-12-16 21:46:06 +00:00
alexsparkes
e259ec9dd4 feat(settings): add titles to options and improve initial render handling in visibility toggle 2024-12-16 19:44:25 +00:00
alexsparkes
c3870b30f3 refactor(slider): enhance performance and readability with memoization and style organization 2024-12-16 19:21:40 +00:00
alexsparkes
1882465588 style(hero): improve controls spacing 2024-12-16 18:58:59 +00:00
alexsparkes
5e35289ae4 fix(slider): light theme styles 2024-12-16 18:55:44 +00:00
alexsparkes
c518d51431 style(slider): enhance hover transition effects for slider marks 2024-12-16 18:52:36 +00:00
alexsparkes
375665a90f refactor(slider): replace mui with react slider 2024-12-16 18:49:07 +00:00
alexsparkes
7e8ad29cbc style(hero buttons): improve micro interactions of buttons with transitions 2024-12-16 18:19:22 +00:00
alexsparkes
4fe3df2a80 feat(date): enhance DateWidget for preview mode and improve font size handling
Co-authored-by: David Ralph <me@davidcralph.co.uk>
2024-12-16 14:51:04 +00:00
alexsparkes
a5a3a18486 feat(date): Date preview 2024-12-16 14:29:39 +00:00
alexsparkes
ae014e46f2 feat(date): implement date widget with short and long date formats
Co-authored-by: David Ralph <me@davidcralph.co.uk>
2024-12-16 14:08:46 +00:00
alexsparkes
a4ae9496a3 style(weather): preview background 2024-12-16 12:52:18 +00:00
alexsparkes
965395bf92 style(clock preview): have transition between types of clock on preview 2024-12-16 02:24:16 +00:00
alexsparkes
ccb836d790 style(hero): Make the tiles uniform with each other 2024-12-15 22:52:28 +00:00
alexsparkes
c51e8fa1d9 fix(clock preview): static time 2024-12-15 22:35:34 +00:00
alexsparkes
ce9089dcee refactor(clock): use context for centralised time management 2024-12-15 21:59:33 +00:00
alexsparkes
973eecabe9 refactor(clock): enhance error handling and optimize rendering with memoization 2024-12-15 19:37:36 +00:00
alexsparkes
71670a8d2c refactor(time): add clock preview and split up functionality 2024-12-15 19:16:23 +00:00
alexsparkes
bad65cfe10 fix(preferences_wrapper): issue with null shown status 2024-12-12 20:56:42 +00:00
alexsparkes
1f62ea966c refactor(PhotoInformation): simplify state management and improve rendering logic
refactor(Widgets): optimize state initialization and event handling
remove(Tabs): delete unused Tabs component
2024-12-12 15:24:44 +00:00
alexsparkes
2febdb4616 chore(gitignore): update to ignore coverage, logs, and temporary files 2024-12-12 12:23:12 +00:00
alexsparkes
5dff2fa91e style(background): transition effect on the background images grid 2024-11-27 20:39:50 +00:00
alexsparkes
c15ce66bb8 refactor(background): use indexeddb for custom images 2024-11-27 19:42:26 +00:00
alexsparkes
b01b26bf86 refactor(achievements): update styling for achievement title and description 2024-11-27 17:27:28 +00:00
alexsparkes
0098bf1047 feat(background): pre-fetching image 2024-11-26 22:07:19 +00:00
alexsparkes
2e2670f275 refactor(background): Further code readaability improvements 2024-11-26 21:56:20 +00:00
alexsparkes
89526d19b9 refactor(background): Converted to functional component + fixed background transition quirk 2024-11-26 21:17:33 +00:00
alexsparkes
ac9eac2948 refactor(background): Split up main file 2024-11-26 18:56:39 +00:00
alexsparkes
9fe0fecb0a Merge branch '8.0' of https://github.com/mue/mue into 8.0 2024-11-26 17:24:52 +00:00
alexsparkes
6f786e68eb refactor(photo-information): Split up into components 2024-11-26 17:24:49 +00:00
John Joseph A. Gatchalian
1f1346c71f Translated using Weblate (English (United States))
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/en_US/
2024-11-26 11:00:26 +00:00
David Ralph
b9764a72fb fix: import settings, prepare to move bg to indexed db 2024-11-18 01:08:56 +00:00
David Ralph
f456168428 fix: missing theme on final welcome, improve hover on radio 2024-11-18 00:54:25 +00:00
John Joseph A. Gatchalian
c1b8b06f1a Translated using Weblate (English (United States))
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/en_US/
2024-11-17 06:00:20 +00:00
Lesnay Manrresa Martínez
fc4298c0f7 Translated using Weblate (Spanish (Latin America))
Currently translated at 72.5% (58 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-11-17 06:00:19 +00:00
John Joseph A. Gatchalian
3c70a893cd Translated using Weblate (English (United States))
Currently translated at 98.7% (79 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/en_US/
2024-11-17 06:00:18 +00:00
alexsparkes
4ec16ac78b fix(stats): Streak logic 2024-11-07 19:21:23 +00:00
alexsparkes
b3be17c11e fix(achievments): Make achievements work with new IndexedDB
- currently has extremely verbose logs in console, to be removed later
2024-11-06 21:51:55 +00:00
alexsparkes
2e2c8b41da feat: stats by indexed db + tab hours clock 2024-11-03 22:01:35 +00:00
alexsparkes
ca0b4820e7 Merge branch '8.0' of https://github.com/mue/mue into 8.0 2024-11-02 23:52:37 +00:00
alexsparkes
ce387117dc Update achievements condition and improve stats tracking logic 2024-11-02 23:52:34 +00:00
Languages add-on
eaee2cf3b6 Added translation using Weblate (Vietnamese) 2024-11-02 06:50:08 +01:00
Languages add-on
6bafb1e0a3 Added translation using Weblate (Vietnamese) 2024-11-02 06:49:50 +01:00
Languages add-on
28bd57bbb4 Added translation using Weblate (Vietnamese) 2024-11-02 06:49:33 +01:00
Languages add-on
9096026bd2 Added translation using Weblate (Vietnamese) 2024-11-02 06:49:16 +01:00
Languages add-on
aa7cd5e545 Added translation using Weblate (Vietnamese) 2024-11-02 06:49:04 +01:00
Languages add-on
840fd161db Added translation using Weblate (Vietnamese) 2024-11-02 06:48:51 +01:00
Mason Mackaman
5856b35b1c Translated using Weblate (English (United States))
Currently translated at 12.5% (10 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/en_US/
2024-10-23 09:22:36 +02:00
LibreTranslate
ae77782239 Translated using Weblate (Spanish (Latin America))
Currently translated at 70.0% (56 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-17 06:19:37 +00:00
Gustavo J. Lopez
1cb982d2bc Translated using Weblate (Spanish (Latin America))
Currently translated at 70.0% (56 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-17 06:19:37 +00:00
Weblate Translation Memory
85f450578a Translated using Weblate (Spanish (Latin America))
Currently translated at 67.5% (54 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-16 19:34:47 +02:00
LibreTranslate
7d62ba2cf7 Translated using Weblate (Spanish (Latin America))
Currently translated at 67.5% (54 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-16 19:34:47 +02:00
Gustavo J. Lopez
219ac24f7c Translated using Weblate (Spanish (Latin America))
Currently translated at 67.5% (54 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-16 19:34:47 +02:00
Gustavo J. Lopez
cfb3e217f5 Translated using Weblate (Spanish (Latin America))
Currently translated at 65.0% (52 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-16 19:33:33 +02:00
Weblate Translation Memory
1d06b081b5 Translated using Weblate (Spanish (Latin America))
Currently translated at 65.0% (52 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-16 19:33:33 +02:00
LibreTranslate
94ca7d3771 Translated using Weblate (Spanish (Latin America))
Currently translated at 65.0% (52 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es_419/
2024-10-16 19:33:33 +02:00
David Ralph
2c424d9e76 chore: borrow the vite deprecation fix from 198918c066 2024-10-14 12:13:19 +01:00
Isaac
a5a801e18a fix: remove extra utm_source query
Signed-off-by: Isaac <git@eartharoid.me>
2024-10-14 12:11:24 +01:00
Arvaidas Rekis
494ec25b13 Translated using Weblate (Azerbaijani (Southern))
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/azb/
2024-10-05 16:15:44 +02:00
Arvaidas Rekis
4ad6e9a5c5 Translated using Weblate (Azerbaijani)
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/az/
2024-10-05 16:15:43 +02:00
Arvaidas Rekis
3746aae577 Translated using Weblate (Slovenian)
Currently translated at 35.0% (28 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/sl/
2024-10-05 16:15:42 +02:00
Arvaidas Rekis
357d323882 Translated using Weblate (French)
Currently translated at 48.7% (39 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fr/
2024-10-05 16:15:41 +02:00
Isaac
f0cd913c49 Added translation using Weblate (Estonian) 2024-10-04 22:14:34 +02:00
Isaac
1f514824d2 Deleted translation using Weblate (Estonian) 2024-10-04 22:14:17 +02:00
Arvaidas Rekis
2da1a53500 Translated using Weblate (Estonian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/et/
2024-10-04 22:13:15 +02:00
Arvaidas Rekis
a53dce6b3a Translated using Weblate (Estonian)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/et/
2024-10-04 22:13:14 +02:00
Arvaidas Rekis
4bc5c8645a Translated using Weblate (Latvian)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/lv/
2024-10-04 22:13:14 +02:00
Arvaidas Rekis
8337295eb7 Translated using Weblate (Estonian)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/et/
2024-10-04 22:13:14 +02:00
Arvaidas Rekis
6e1819b8dc Translated using Weblate (Latvian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/lv/
2024-10-04 22:13:13 +02:00
Arvaidas Rekis
a03d4db0fb Translated using Weblate (Latvian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/lv/
2024-10-04 22:13:11 +02:00
Arvaidas Rekis
eefa7f56ca Translated using Weblate (Lithuanian)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/lt/
2024-10-04 22:13:10 +02:00
Arvaidas Rekis
42e1cf573d Translated using Weblate (Lithuanian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/lt/
2024-10-04 22:13:10 +02:00
Arvaidas Rekis
86a604132d Translated using Weblate (Lithuanian)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/lt/
2024-10-04 22:13:10 +02:00
Arvaidas Rekis
843b8692f1 Translated using Weblate (Latvian)
Currently translated at 8.6% (4 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/lv/
2024-10-04 19:42:08 +02:00
Arvaidas Rekis
877043a805 Translated using Weblate (Latvian)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/lv/
2024-10-04 19:42:08 +02:00
Arvaidas Rekis
573ba1217b Translated using Weblate (Latvian)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/lv/
2024-10-04 19:42:08 +02:00
Arvaidas Rekis
4b786f0c90 Translated using Weblate (Estonian)
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/et/
2024-10-04 12:16:24 +00:00
Arvaidas Rekis
ea78adff35 Translated using Weblate (Latvian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lv/
2024-10-04 12:16:23 +00:00
Languages add-on
be5feac659 Added translation using Weblate (Estonian) 2024-10-04 01:21:25 +02:00
Languages add-on
a2cd8afc13 Added translation using Weblate (Estonian) 2024-10-04 01:18:18 +02:00
Languages add-on
73d80e123c Added translation using Weblate (Estonian) 2024-10-04 01:18:06 +02:00
Languages add-on
07fe459835 Added translation using Weblate (Estonian) 2024-10-04 01:11:54 +02:00
Languages add-on
40eecd94a5 Added translation using Weblate (Estonian) 2024-10-04 01:11:40 +02:00
Languages add-on
77e7015434 Added translation using Weblate (Latvian) 2024-10-03 23:11:35 +00:00
Languages add-on
97afa3f8cc Added translation using Weblate (Estonian) 2024-10-04 01:11:30 +02:00
Languages add-on
43d1291535 Added translation using Weblate (Latvian) 2024-10-03 23:11:29 +00:00
Languages add-on
a5adb443aa Added translation using Weblate (Latvian) 2024-10-03 23:11:20 +00:00
Languages add-on
57835ea028 Added translation using Weblate (Latvian) 2024-10-04 01:11:09 +02:00
Languages add-on
77c90a977b Added translation using Weblate (Latvian) 2024-10-04 01:11:04 +02:00
Languages add-on
3ac7b1f3e1 Added translation using Weblate (Latvian) 2024-10-04 01:10:56 +02:00
Arvaidas Rekis
29f75a4520 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-04 01:10:55 +02:00
Isaac
77c7c3995f delete files from bad merge 2024-10-03 23:39:56 +01:00
Isaac
90a23fc0b0 fix: CI builds (update i18n) 2024-10-03 23:37:40 +01:00
Arvaidas Rekis
19f80ebd1f Translated using Weblate (Lithuanian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/lt/
2024-10-03 20:30:49 +02:00
Weblate Translation Memory
18e357e19e Translated using Weblate (Lithuanian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/lt/
2024-10-03 20:30:49 +02:00
Weblate Translation Memory
c9c58e81da Translated using Weblate (Lithuanian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/lt/
2024-10-03 20:30:48 +02:00
Weblate Translation Memory
9aae99e226 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/lt/
2024-10-03 20:09:19 +02:00
Arvaidas Rekis
7b04118280 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/lt/
2024-10-03 20:07:34 +02:00
Arvaidas Rekis
37caa70670 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/lt/
2024-10-03 20:07:33 +02:00
Arvaidas Rekis
36889e13ef Translated using Weblate (Lithuanian)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/lt/
2024-10-03 20:07:33 +02:00
Arvaidas Rekis
588892a668 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 20:07:33 +02:00
Arvaidas Rekis
09428cac3b Translated using Weblate (Lithuanian)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/lt/
2024-10-03 20:07:33 +02:00
Arvaidas Rekis
0cecec8440 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/lt/
2024-10-03 20:07:32 +02:00
Arvaidas Rekis
32248ee490 Translated using Weblate (Lithuanian)
Currently translated at 78.7% (63 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 19:50:05 +02:00
Arvaidas Rekis
d93b8a4ae2 Translated using Weblate (Lithuanian)
Currently translated at 78.7% (63 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 19:50:04 +02:00
Weblate Translation Memory
88a50e61e4 Translated using Weblate (Lithuanian)
Currently translated at 78.7% (63 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 19:50:02 +02:00
Arvaidas Rekis
481f526b86 Translated using Weblate (Lithuanian)
Currently translated at 78.7% (63 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 19:50:02 +02:00
Arvaidas Rekis
4057909f9b Translated using Weblate (Lithuanian)
Currently translated at 68.7% (55 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 11:05:11 +02:00
Weblate Translation Memory
6f6a0d5f59 Translated using Weblate (Lithuanian)
Currently translated at 68.7% (55 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/lt/
2024-10-03 11:05:11 +02:00
Languages add-on
0d4dc1f921 Added translation using Weblate (Lithuanian) 2024-10-03 02:44:54 +02:00
Languages add-on
77c2e1237b Added translation using Weblate (Lithuanian) 2024-10-03 02:44:46 +02:00
Languages add-on
2a3dfe6403 Added translation using Weblate (Lithuanian) 2024-10-03 02:44:39 +02:00
Languages add-on
45d4637caa Added translation using Weblate (Lithuanian) 2024-10-03 02:44:27 +02:00
Languages add-on
d4f1de07fe Added translation using Weblate (Lithuanian) 2024-10-03 02:44:22 +02:00
Languages add-on
42c332f433 Added translation using Weblate (Lithuanian) 2024-10-03 02:44:21 +02:00
alexsparkes
93ff9217bd refactor: convert more to new settings layout 2024-09-27 20:59:36 +01:00
David Ralph
03074647e9 Merge branch '8.0' of https://github.com/mue/mue into 8.0 2024-09-27 20:05:49 +01:00
David Ralph
0c6bae9a90 fix: rename date function to fix imports 2024-09-27 20:05:34 +01:00
Jose Delvani
78c48adfbf Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (313 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/pt_BR/
2024-09-20 22:30:20 +00:00
gallegonovato
1152c7feca Translated using Weblate (Spanish)
Currently translated at 86.9% (272 of 313 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/es/
2024-09-20 22:30:19 +00:00
David Ralph
728ef587e1 refactor: move some date things about and separate, remove unnecessary files 2024-09-20 23:30:07 +01:00
David Ralph
9393c20ea8 Merge remote-tracking branch 'origin/main' into 8.0 2024-09-15 20:17:47 +01:00
David Ralph
20319d0b8e chore: new readme v1 2024-09-15 20:13:38 +01:00
dependabot[bot]
28e7d0c0fd chore(deps-dev): bump stylelint-scss from 6.5.1 to 6.6.0 (#860)
Bumps [stylelint-scss](https://github.com/stylelint-scss/stylelint-scss) from 6.5.1 to 6.6.0.
- [Release notes](https://github.com/stylelint-scss/stylelint-scss/releases)
- [Changelog](https://github.com/stylelint-scss/stylelint-scss/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stylelint-scss/stylelint-scss/compare/v6.5.1...v6.6.0)

---
updated-dependencies:
- dependency-name: stylelint-scss
  dependency-type: direct:development
  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>
2024-09-13 08:38:05 +00:00
dependabot[bot]
1e36c3268a chore(deps): bump embla-carousel-react from 8.2.1 to 8.3.0 (#859)
Bumps [embla-carousel-react](https://github.com/davidjerleke/embla-carousel) from 8.2.1 to 8.3.0.
- [Release notes](https://github.com/davidjerleke/embla-carousel/releases)
- [Commits](https://github.com/davidjerleke/embla-carousel/compare/v8.2.1...v8.3.0)

---
updated-dependencies:
- dependency-name: embla-carousel-react
  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>
2024-09-13 08:37:52 +00:00
Isaac
80e2c37751 fix(manifest): firefox addon id (#851) 2024-09-12 17:02:46 +01:00
Isaac
32a4c1e72e fix(manifest): another attempt to fix firefox 2024-09-12 16:56:49 +01:00
Isaac
8f8004d4cf fix(achievements): i18n 2024-09-12 16:33:49 +01:00
Isaac
63db18d228 chore(deps): update lockfile 2024-09-12 16:33:23 +01:00
dependabot[bot]
bb57c215aa chore(deps): bump @mui/material from 6.0.2 to 6.1.0 (#858)
Bumps [@mui/material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material) from 6.0.2 to 6.1.0.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v6.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>
2024-09-12 08:58:23 +00:00
dependabot[bot]
58ac84bdc3 chore(deps-dev): bump husky from 9.1.5 to 9.1.6 (#857)
Bumps [husky](https://github.com/typicode/husky) from 9.1.5 to 9.1.6.
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v9.1.5...v9.1.6)

---
updated-dependencies:
- dependency-name: husky
  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>
2024-09-12 08:58:09 +00:00
dependabot[bot]
f8f89d236c chore(deps-dev): bump @commitlint/config-conventional (#856)
Bumps [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional) from 19.4.1 to 19.5.0.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.5.0/@commitlint/config-conventional)

---
updated-dependencies:
- dependency-name: "@commitlint/config-conventional"
  dependency-type: direct:development
  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>
2024-09-11 08:54:45 +00:00
dependabot[bot]
afbdce3d5f chore(deps-dev): bump vite from 5.4.3 to 5.4.4 (#855)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.3 to 5.4.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.4/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  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>
2024-09-11 08:52:57 +00:00
dependabot[bot]
a7980e6941 chore(deps): bump @sentry/react from 8.29.0 to 8.30.0 (#854)
Bumps [@sentry/react](https://github.com/getsentry/sentry-javascript) from 8.29.0 to 8.30.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/8.29.0...8.30.0)

---
updated-dependencies:
- dependency-name: "@sentry/react"
  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>
2024-09-11 08:52:42 +00:00
dependabot[bot]
7f3e4171a3 chore(deps-dev): bump @commitlint/cli from 19.4.1 to 19.5.0 (#853)
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 19.4.1 to 19.5.0.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.5.0/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-type: direct:development
  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>
2024-09-11 08:52:23 +00:00
dependabot[bot]
7157493327 chore(deps): bump @sentry/react from 8.28.0 to 8.29.0 (#852)
Bumps [@sentry/react](https://github.com/getsentry/sentry-javascript) from 8.28.0 to 8.29.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/8.28.0...8.29.0)

---
updated-dependencies:
- dependency-name: "@sentry/react"
  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>
2024-09-10 08:47:22 +00:00
LibreTranslate
238ef75623 Translated using Weblate (Turkish)
Currently translated at 100.0% (312 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/tr/
2024-09-08 16:46:50 +02:00
Kağan Can Şit
6afe0bc42e Translated using Weblate (Turkish)
Currently translated at 100.0% (312 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/tr/
2024-09-08 16:46:50 +02:00
Weblate Translation Memory
145e7986a2 Translated using Weblate (Turkish)
Currently translated at 100.0% (312 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/tr/
2024-09-08 16:46:50 +02:00
LibreTranslate
d5b24ddb68 Translated using Weblate (Turkish)
Currently translated at 95.8% (299 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/tr/
2024-09-08 16:39:24 +02:00
Weblate Translation Memory
c2c8be5a6e Translated using Weblate (Turkish)
Currently translated at 95.8% (299 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/tr/
2024-09-08 16:39:24 +02:00
Weblate Translation Memory
6bba7dbe9d Translated using Weblate (Turkish)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/tr/
2024-09-08 16:39:24 +02:00
Kağan Can Şit
76066186dd Translated using Weblate (Turkish)
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/tr/
2024-09-08 16:39:24 +02:00
Kağan Can Şit
fd594bddf9 Translated using Weblate (Turkish)
Currently translated at 93.4% (43 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/tr/
2024-09-08 16:33:13 +02:00
Weblate Translation Memory
cf5820f73b Translated using Weblate (Turkish)
Currently translated at 93.4% (43 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/tr/
2024-09-08 16:33:12 +02:00
Kağan Can Şit
e6c631826b Translated using Weblate (Turkish)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/tr/
2024-09-08 16:33:12 +02:00
Kağan Can Şit
c707081985 Translated using Weblate (Turkish)
Currently translated at 95.8% (23 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/tr/
2024-09-08 16:33:12 +02:00
LibreTranslate
c7737b6ebf Translated using Weblate (Turkish)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/tr/
2024-09-08 16:18:58 +02:00
Kağan Can Şit
8534acb3ee Translated using Weblate (Turkish)
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/tr/
2024-09-08 16:18:58 +02:00
LibreTranslate
115bbe63d8 Translated using Weblate (Turkish)
Currently translated at 41.6% (10 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/tr/
2024-09-08 16:18:58 +02:00
Kağan Can Şit
ad2f836451 Translated using Weblate (Turkish)
Currently translated at 41.6% (10 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/tr/
2024-09-08 16:18:58 +02:00
Kağan Can Şit
e60009d372 Translated using Weblate (Turkish)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/tr/
2024-09-08 16:18:58 +02:00
Weblate Translation Memory
197b7eb725 Translated using Weblate (Turkish)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/tr/
2024-09-08 16:18:58 +02:00
gallegonovato
940af56a2b Translated using Weblate (Spanish)
Currently translated at 100.0% (500 of 500 strings)

Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-7-1/es/
Translation: Mue/Mue Tab 7.1
2024-09-07 15:09:19 +02:00
Isaac
ea20d3e518 fix(manifest): add ID to Firefox manifest 2024-09-06 19:18:10 +01:00
Isaac
837836ab79 chore(dependencies): update lockfile 2024-09-06 19:17:47 +01:00
David Ralph
bc104c49af fix: embarrassing translation update mistake (not bumping ver for this) 2024-09-06 13:08:41 +01:00
David Ralph
ed6f660099 feat: rewrite stats backend 2024-09-03 14:06:13 +01:00
hugoalh
742b762ae2 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/zh_Hant/
2024-08-31 20:09:20 +02:00
hugoalh
61e8a956c9 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 95.8% (23 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/zh_Hant/
2024-08-31 20:09:19 +02:00
Languages add-on
83c3949b31 Added translation using Weblate (Chinese (Traditional)) 2024-08-31 05:17:07 +00:00
Languages add-on
719de2891e Added translation using Weblate (Chinese (Traditional)) 2024-08-31 05:17:02 +00:00
Languages add-on
df4e5e6732 Added translation using Weblate (Chinese (Traditional)) 2024-08-31 05:17:00 +00:00
Languages add-on
e770c12230 Added translation using Weblate (Chinese (Traditional)) 2024-08-31 07:16:51 +02:00
Languages add-on
8826b699b2 Added translation using Weblate (Chinese (Traditional)) 2024-08-31 07:16:50 +02:00
Languages add-on
fbd888bb99 Added translation using Weblate (Chinese (Traditional)) 2024-08-31 07:16:48 +02:00
gallegonovato
850bd2e1a6 Translated using Weblate (Spanish)
Currently translated at 91.6% (22 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/es/
2024-08-26 01:09:19 +00:00
gallegonovato
52390dc14d Translated using Weblate (Spanish)
Currently translated at 91.6% (22 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/es/
2024-08-25 14:12:55 +02:00
Freesourceman
bc95a0a794 Translated using Weblate (Spanish)
Currently translated at 91.6% (22 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/es/
2024-08-25 14:12:55 +02:00
gallegonovato
ed3e70f973 Translated using Weblate (Spanish)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/es/
2024-08-25 14:12:55 +02:00
David Ralph
75845d49f9 Merge branch '8.0' of https://github.com/mue/mue into 8.0 2024-08-24 00:42:49 +01:00
David Ralph
2ada19f449 chore: reorganise dependencies, change working ver to 8.0 2024-08-24 00:42:43 +01:00
alexsparkes
e5a175db47 fix: inconsistent spacing 2024-08-24 00:39:54 +01:00
David Ralph
67649d1985 chore: run prettier, lint, make it so i can run mue 2024-08-24 00:27:59 +01:00
alexsparkes
030c056aed refactor(time options): Apply new layout to time options 2024-08-24 00:22:51 +01:00
alexsparkes
f7bbf04070 refactor(weather options): New tile-focused approach to options pages
Co-authored-by: David Ralph <me@davidcralph.co.uk>
2024-08-24 00:13:56 +01:00
alexsparkes
ae8d9de411 style: new theme selector 2024-08-21 21:57:45 +01:00
alexsparkes
2ddfdb24dd fix: background options' routing & section icon shrink
Co-authored-by: David Ralph <me@davidcralph.co.uk>
2024-08-21 15:16:19 +01:00
David Ralph
01b89541c0 refactor: about functional component, reimplement abort controller 2024-08-21 14:26:46 +01:00
David Ralph
0c4e21dd50 refactor: turn backgroundoptions into a functional component 2024-08-21 14:19:23 +01:00
alexsparkes
bc73f4ebfa fix(preferences wrapper): fade out animation 2024-08-19 23:01:11 +01:00
alexsparkes
f48b7044ac refactor: better organise options orders 2024-08-19 22:48:33 +01:00
alexsparkes
ccff5d3f6a fix: background locale error 2024-08-18 19:06:43 +01:00
alexsparkes
080cf484f4 fix(changelog): Sizing issue 2024-08-18 18:59:45 +01:00
alexsparkes
74fd732c40 refacotr: settings options layout 2024-08-18 18:58:02 +01:00
Languages add-on
e5cfb6042a Added translation using Weblate (Azerbaijani (Southern)) 2024-08-18 12:56:16 +02:00
Languages add-on
13f77d9a90 Added translation using Weblate (Azerbaijani (Southern)) 2024-08-18 12:56:11 +02:00
Languages add-on
2a259d9cfd Added translation using Weblate (Azerbaijani (Southern)) 2024-08-18 12:56:07 +02:00
Languages add-on
9c5cd2a9b6 Added translation using Weblate (Azerbaijani (Southern)) 2024-08-18 10:49:30 +00:00
Languages add-on
4063d82abb Added translation using Weblate (Azerbaijani (Southern)) 2024-08-18 10:49:25 +00:00
Languages add-on
c09722ac76 Added translation using Weblate (Azerbaijani (Southern)) 2024-08-18 10:49:20 +00:00
Languages add-on
9727d34afb Added translation using Weblate (Azerbaijani) 2024-08-18 10:48:57 +00:00
Languages add-on
ddaa1669d0 Added translation using Weblate (Azerbaijani) 2024-08-18 12:48:45 +02:00
Languages add-on
3424ea1193 Added translation using Weblate (Azerbaijani) 2024-08-18 12:48:37 +02:00
Languages add-on
38dd2eb250 Added translation using Weblate (Azerbaijani) 2024-08-18 10:48:32 +00:00
Languages add-on
8e4a2e72b4 Added translation using Weblate (Azerbaijani) 2024-08-18 10:48:29 +00:00
Languages add-on
e273d27b30 Added translation using Weblate (Azerbaijani) 2024-08-18 10:48:26 +00:00
shichen437
3593059c01 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/zh_Hans/
2024-08-18 10:48:24 +00:00
alexsparkes
bf64f56f7c refactor: begin redesign of tab errors 2024-08-17 23:50:13 +01:00
alexsparkes
7178983a36 refactor: more converting modal to tailwind 2024-08-17 20:09:51 +01:00
alexsparkes
187c008e41 refactor: begin converting modal from sass to tailwind 2024-08-17 19:12:08 +01:00
aliaidany
1a10721dd1 Translated using Weblate (Persian)
Currently translated at 1.2% (1 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/fa/
2024-08-13 09:09:16 +02:00
Languages add-on
2a8fbd515f Added translation using Weblate (Persian) 2024-08-12 20:14:30 +02:00
Languages add-on
85b9082bec Added translation using Weblate (Persian) 2024-08-12 20:14:27 +02:00
Languages add-on
e48e875341 Added translation using Weblate (Persian) 2024-08-12 20:14:23 +02:00
Languages add-on
31f446c96e Added translation using Weblate (Persian) 2024-08-12 20:13:51 +02:00
Languages add-on
4436cdb037 Added translation using Weblate (Persian) 2024-08-12 20:13:46 +02:00
Languages add-on
81716c19fa Added translation using Weblate (Persian) 2024-08-12 20:13:42 +02:00
Leonardo-ConectaTech
6b185fb9a8 Translated using Weblate (Portuguese)
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/pt/
2024-08-10 11:09:14 +02:00
Leonardo-ConectaTech
9367f340d7 Translated using Weblate (Portuguese)
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/pt/
2024-08-10 11:09:13 +02:00
Leonardo-ConectaTech
1177d6d8aa Translated using Weblate (Portuguese)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/pt/
2024-08-10 11:09:12 +02:00
Evgeniy Khramov
89ffc60d7a Translated using Weblate (Russian)
Currently translated at 97.8% (45 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/ru/
2024-08-08 00:09:21 +02:00
LibreTranslate
065fcb6c53 Translated using Weblate (Russian)
Currently translated at 97.8% (45 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/ru/
2024-08-08 00:09:20 +02:00
Evgeniy Khramov
7c3206bb32 Translated using Weblate (Russian)
Currently translated at 69.2% (27 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/ru/
2024-08-08 00:09:20 +02:00
Weblate Translation Memory
34e315cc47 Translated using Weblate (Russian)
Currently translated at 69.2% (27 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/ru/
2024-08-08 00:09:19 +02:00
Evgeniy Khramov
ca52f626a8 Translated using Weblate (Russian)
Currently translated at 95.8% (23 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/ru/
2024-08-08 00:09:18 +02:00
LibreTranslate
d26c7e3f3c Translated using Weblate (Russian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ru/
2024-08-08 00:09:18 +02:00
Weblate Translation Memory
8e6fe09971 Translated using Weblate (Russian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ru/
2024-08-08 00:09:17 +02:00
Evgeniy Khramov
793983907a Translated using Weblate (Russian)
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/ru/
2024-08-08 00:09:16 +02:00
David C
69b37335de Translated using Weblate (Slovenian)
Currently translated at 20.5% (8 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/sl/
2024-07-28 07:09:27 +00:00
David C
c71d87a70c Translated using Weblate (Slovenian)
Currently translated at 35.0% (28 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/sl/
2024-07-28 07:09:26 +00:00
Languages add-on
f1f62b9932 Added translation using Weblate (Slovenian) 2024-07-27 20:00:40 +02:00
Languages add-on
c6298c6c15 Added translation using Weblate (Slovenian) 2024-07-27 20:00:33 +02:00
Languages add-on
a9af955c71 Added translation using Weblate (Slovenian) 2024-07-27 20:00:29 +02:00
Languages add-on
cdadbe9e3b Added translation using Weblate (Slovenian) 2024-07-27 20:00:17 +02:00
Languages add-on
24329b3bba Added translation using Weblate (Slovenian) 2024-07-27 20:00:12 +02:00
Languages add-on
7fb5def05b Added translation using Weblate (Slovenian) 2024-07-27 20:00:08 +02:00
Jose Delvani
5a2a1b864c Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (312 of 312 strings)

Translation: Mue/Mue Tab - Settings
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-settings/pt_BR/
2024-07-27 16:09:29 +02:00
Jose Delvani
ab30e7306b Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (46 of 46 strings)

Translation: Mue/Mue Tab - Marketplace
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-marketplace/pt_BR/
2024-07-27 16:09:28 +02:00
Jose Delvani
5fccbfdde1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (39 of 39 strings)

Translation: Mue/Mue Tab - Welcome
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-welcome/pt_BR/
2024-07-27 16:09:28 +02:00
Jose Delvani
9af839c317 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (23 of 23 strings)

Translation: Mue/Mue Tab - Addons
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-addons/pt_BR/
2024-07-27 16:09:27 +02:00
Jose Delvani
f7c2ed0c01 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (24 of 24 strings)

Translation: Mue/Mue Tab - Achievements
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-achievements/pt_BR/
2024-07-27 16:09:26 +02:00
Jose Delvani
a28c694cdb Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (80 of 80 strings)

Translation: Mue/Mue Tab - Main
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/pt_BR/
2024-07-27 16:09:25 +02:00
Anonymous
76cce3fbd2 Translated using Weblate (Indonesian)
Currently translated at 86.2% (69 of 80 strings)

Translation: Mue/Mue Tab (Main)
Translate-URL: https://hosted.weblate.org/projects/mue/mue-tab-8-0/mue-tab-main/id/
2024-06-23 12:09:42 +02:00
alexsparkes
5495b5c0a9 style: radio group 2024-06-22 10:10:17 +01:00
Isaac
4fdb1e5ecc fix: revert accidental name change 2024-06-22 03:27:27 +01:00
Isaac
a4ba74efed chore: remove unused files 2024-06-22 02:22:06 +01:00
Isaac
9883f28717 fix: build process, static assets 2024-06-22 02:07:37 +01:00
Isaac
4f7ad214ad fix: build targets 2024-06-22 00:04:52 +01:00
Isaac
56838348c5 fix: last language being hidden behind button bar 2024-06-22 00:04:34 +01:00
Isaac
835e708ccd chore(i18n): use fixed import 2024-06-21 22:17:54 +01:00
Isaac
ccbe778908 feat(i18n): finish redoing translations 2024-06-21 22:01:15 +01:00
alexsparkes
3c73f03b78 refactor(items): Move filter and display to seperate file 2024-06-21 15:28:57 +01:00
alexsparkes
2250a86ef9 style: show if item is installed on marketplace 2024-06-21 14:23:20 +01:00
alexsparkes
9e579f0444 style: cleanup items list 2024-06-21 13:39:02 +01:00
alexsparkes
0fbad3cfda fix: Quote and Background automatic types 2024-06-21 13:18:29 +01:00
David Ralph
10e7a3ce63 fix: background photo packs, declutter 2024-06-21 12:08:02 +01:00
alexsparkes
a6597af965 refactor(marketplace): reduce redundancies 2024-06-20 23:37:04 +01:00
Isaac
fe2cac9632 style: browse and item pages 2024-06-20 23:22:37 +01:00
Isaac
c9740191e1 fix: variable fonts
Co-authored-by: Alex Sparkes <alexsparkes@gmail.com>
2024-06-20 22:15:50 +01:00
alexsparkes
2f711195a4 feat: Use similar functionality for photo packs 2024-06-20 15:45:49 +01:00
alexsparkes
cb54e705ee refactor: Rewrite marketplace quote pack logic entirely 2024-06-20 14:21:00 +01:00
David Ralph
dfcd509b96 feat(marketplace): add install/uninstall logic back (WIP) 2024-06-20 00:20:33 +01:00
alexsparkes
09e35028ec fix: Install + Uninstall item 2024-06-19 23:57:47 +01:00
Isaac
c48d66768b style: item card hover with gradient transition 2024-06-19 22:28:55 +01:00
alexsparkes
eb0da6e71e fix: item organisation 2024-06-19 15:55:46 +01:00
alexsparkes
28995a6ad3 fix(marketplace): Collection page 2024-06-19 12:38:11 +01:00
Isaac
258fc9dc50 style: radial gradient ItemPage sidebar, replacing blurred image 2024-06-19 02:58:24 +01:00
Isaac
49d777842b style: radial gradient item card backgrounds 2024-06-19 02:17:57 +01:00
alexsparkes
4078809c13 refactor: Changes to translations 2024-06-18 18:30:52 +01:00
alexsparkes
d46b1b1749 style(marketplace): Transition between items view options
Co-authored-by: Isaac <contact@eartharoid.me>
2024-06-18 17:31:39 +01:00
alexsparkes
c97841701a fix(collection): Unnecessary re-render 2024-06-18 15:46:47 +01:00
alexsparkes
8b5b6fe18a refactor(marketplace): Reduce lines 2024-06-18 15:38:05 +01:00
alexsparkes
9c900c6484 refactor(marketplace): WIP implementation of collection 2024-06-18 15:12:09 +01:00
alexsparkes
3f2f3fdfa3 refactor(marketplace): Context for marketplace data 2024-06-18 11:04:51 +01:00
Isaac
81b88e0846 chore: remove now unneeded script 2024-06-18 00:09:12 +01:00
Isaac
9dc169a8a6 fix: rename SVG attributes 2024-06-18 00:05:35 +01:00
Isaac
63443ab1cc refactor(translations): mostly finish upgrading to i18n v2 2024-06-18 00:04:07 +01:00
Isaac
287c9a1b18 chore: add vite inspector 2024-06-17 20:29:23 +01:00
alexsparkes
a03da9c10b refactor(translations): Use new translation package
Co-authored-by: Isaac <contact@eartharoid.me>
2024-06-17 00:15:09 +01:00
alexsparkes
a33c4a97c7 refactor(marketplace): Item Page Progress 2024-06-16 22:21:22 +01:00
alexsparkes
0116c25ddd refactor(marketplace): Item page alterations 2024-06-16 18:47:36 +01:00
Isaac
df38977b65 build: replace pnpm with bun 2024-06-15 18:33:39 +01:00
David Ralph
0ade541501 refactor: entirely reorganise search widget 2024-06-15 12:05:13 +01:00
David Ralph
de3ef5a93f refactor: cleanup and split quote custom settings 2024-06-15 11:48:55 +01:00
David Ralph
9fa4d6d2d8 Merge branch '8.0' of https://github.com/mue/mue into 8.0 2024-06-15 11:35:35 +01:00
David Ralph
9f27af17fb refactor: mostly finish settings transition 2024-06-15 11:35:29 +01:00
alexsparkes
3ab5889e73 refactor(marketplace): full rewrite, very broken 2024-06-15 11:25:19 +01:00
Isaac
4812b9e602 style: sidebar was better before 2024-06-15 00:57:48 +01:00
Isaac
47c2d94154 style: modal loader, sidebar colours 2024-06-15 00:55:10 +01:00
David Ralph
b2a1869089 fix: less bricks due to settings change 2024-06-15 00:06:58 +01:00
alexsparkes
15cea9bc3d feat: cross-modal tab navigation 2024-06-14 23:50:47 +01:00
alexsparkes
bb05575437 fix: translation support for new breadrcrumbs 2024-06-14 22:27:32 +01:00
alexsparkes
428e7ae00f style: glass effect on modal 2024-06-14 21:58:13 +01:00
David Ralph
0e383ccc0d fix: continue conversion of settings system 2024-06-14 19:51:43 +01:00
David Ralph
a7ba47d15b refactor: move more purecomponents to functions 2024-06-14 19:13:09 +01:00
alexsparkes
4747dea06b refactor: Convert pure components to functional components
Co-authored-by: David Ralph <me@davidcralph.co.uk>
Co-authored-by: Isaac <contact@eartharoid.me>
2024-06-14 18:51:36 +01:00
alexsparkes
0f9393d3e6 refactor: move search away from marketplace 2024-06-14 00:06:11 +01:00
alexsparkes
f7d8104531 fix: show current tab 2024-06-13 22:47:12 +01:00
alexsparkes
7fdc8d322a style: new transition between modal tabs 2024-06-13 19:57:09 +01:00
alexsparkes
ac05778757 style(modal): experiments 2024-06-12 23:26:32 +01:00
alexsparkes
ea7343513d style: radical modal redesign 2024-06-12 22:02:52 +01:00
David Ralph
ed1b1a2f6d refactor: keep implementing default options, change some components to functional
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
2024-06-11 16:11:10 +01:00
David Ralph
5aac518cec chore: add remaining default options 2024-06-11 12:28:47 +01:00
alexsparkes
bf1d1660e4 refactor: feature based defaults
Co-authored-by: David Ralph <me@davidcralph.co.uk>
Co-authored-by: Isaac <contact@eartharoid.me>
2024-06-11 11:13:17 +01:00
alexsparkes
8e993b4f93 refactor(input + textarea): Use HeadlessUI 2024-06-10 16:58:15 +01:00
alexsparkes
55e9e74294 style(tooltip): New tooltip animation 2024-06-09 18:12:48 +01:00
alexsparkes
20b5c0b593 style: use non-arbitary value for transition 2024-06-09 17:44:27 +01:00
alexsparkes
78ce68b30b fix: strange viewport issue on welcome 2024-06-09 11:02:37 +01:00
alexsparkes
de319c038c refactor(switch): Use HeadlessUI 2024-06-09 10:13:32 +01:00
alexsparkes
ef4764b3d4 fix(welcome): Finish button 2024-06-09 09:24:55 +01:00
alexsparkes
248293ed97 fix(welcome): Preview feature 2024-06-09 09:05:12 +01:00
alexsparkes
dc2df92cc0 fix(welcome): scrolling on content panel 2024-06-09 00:58:10 +01:00
alexsparkes
303aa60624 style: carousel like animation on welcome 2024-06-09 00:56:16 +01:00
alexsparkes
085377cca9 refactor(welcome): Reimagining of the introductory user experience 2024-06-08 23:54:40 +01:00
David Ralph
7670a07ca2 chore: merge main into 8.0 2024-06-08 18:24:33 +01:00
alexsparkes
813e05e9c2 refactor(settingsrow): Stylistic code change 2024-06-05 15:03:44 +01:00
alexsparkes
c1f470f73f style(checkbox): Match mui design
Co-authored-by: David Ralph <me@davidcralph.co.uk>
2024-06-05 14:40:29 +01:00
alexsparkes
2c98737e21 refactor(checkbox): Functional component and headless UI 2024-06-05 13:56:53 +01:00
alexsparkes
8e7571adbc fix: dropdown bugs 2024-06-05 10:10:19 +01:00
alexsparkes
0b3802fcd6 refactor: changelog use markdown 2024-06-04 18:16:56 +01:00
alexsparkes
143c93364f refactor: begin transition of mui to headless ui + tailwind 2024-06-04 17:28:35 +01:00
534 changed files with 23791 additions and 25908 deletions

11
.gitignore vendored
View File

@@ -2,17 +2,26 @@
node_modules/
.history/
.vscode/
build/
extensions/
.idea/
dist/
build/
coverage/
logs/
# Files
package-lock.json
.stylelintcache
yarn-error.log
pnpm-lock.yaml
.eslintcache
stats.json
yarn.lock
keys.json
.DS_Store
*.zip
i18n-fallback.json
bun.lockb
.env
*.log
*.tmp

129
README.md
View File

@@ -1,121 +1,50 @@
<img src="assets/logo.png" align="left" width="180px" height="180px"/>
<img align="left" width="0" height="192px" hspace="10"/>
![Mue Header](assets/mue_readme.png)
> <a href="https://muetab.com/">Mue</a>
<h1 align="center">Mue</h1>
[![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)
<p align="center">A fast, open and free-to-use browser extension that gives a new, fresh and customisable tab page to modern browsers.</p>
Mue is a fast, open and free-to-use browser extension that gives a new, fresh and customisable tab page to modern browsers.
<p align="center"><i>Managed by <a href="https://kaiso.one" target="_blank">Kaiso</a> and maintained by contributors all over the world.</i></p>
<br>
<p align="center"><a href="https://muetab.com">muetab.com</a></p>
## Table of contents
- [Table of contents](#table-of-contents)
- [Screenshots](#screenshots)
- [Features](#features)
- [Planned Features](#planned-features)
- [Installation](#installation)
- [Chrome](#chrome)
- [Firefox](#firefox)
- [Edge (Chromium)](#edge-chromium)
- [Whale](#whale)
- [Other](#other)
- [Development](#development)
- [Translations](#translations)
- [Credits](#credits)
- [Developers](#developers)
- [Translators](#translators)
- [Contributors](#contributors)
- [Resources](#resources)
## Screenshots
![Screenshot](assets/screenshot.webp)
![Settings Modal](assets/screenshot2.webp)
## Features
- Fast and free
- Supports multiple browsers
- Actively developed and open source
- 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](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://trello.com/b/w7zhS7Hi/mue-50). We are currently working on a rewrite over on the "phoenix" branch.
## Why Mue?
- Beautiful and Minimalist Design
- Customisable Layout
- Widgets (such as weather, notes, bookmarks and more)
- Privacy-Focused - does not track your browsing activity
- Extensible with the Mue Marketplace
- Open Source under the BSD-3 License
## Installation
Mue can be downloaded on the following browsers:
_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](https://chromewebstore.google.com/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
- [Edge](https://microsoftedge.microsoft.com/addons/detail/mue/aepnglgjfokepefimhbnibfjekidhmja)
- [Firefox](https://addons.mozilla.org/en-GB/firefox/addon/mue/)
- [Whale](https://store.whale.naver.com/detail/ecllekeilcmicbfkkiknfdddbogibbnc)
### Chrome
and can be manually sideloaded on others using the files on [GitHub Releases](https://github.com/mue/mue/releases)
[![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
<br>
[Chrome Web Store](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
### Firefox
## Demo
A fully-featured demo of the tab extension is available in-browser at [demo.muetab.com](https://demo.muetab.com)
[![Firefox Add-ons Logo](assets/firefox.png)](https://addons.mozilla.org/firefox/addon/mue)
<br>
[Firefox Add-ons](https://addons.mozilla.org/firefox/addon/mue)
### Edge (Chromium)
[Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja)
### Whale
[Whale Store](https://store.whale.naver.com/detail/ecllekeilcmicbfkkiknfdddbogibbnc)
### Other
[GitHub Releases](https://github.com/mue/mue/releases)
## Development
Install dependencies with ``bun install``, and then you can run any of the following scripts as needed:
Please see the [documentation](https://docs.muetab.com/development#mue-tab).
- `bun run dev[:host]` - start development server
- `bun run build` - build production copy of Mue
- `bun run lint[:fix]` - run linter
- `bun run pretty` - run prettier
- `bun run translations` - migrate old translation format to new
### Translations
[![Contribute on Weblate](https://hosted.weblate.org/widgets/mue/-/open-graph.png)](https://hosted.weblate.org/engage/mue/)
## Credits
### Developers
[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/>
[Aksal](https://github.com/aksalsf) - Indonesian <br/>
[Kağan Can Şit](https://github.com/KaganCanSit) - Turkish <br/>
efeaydal - Turkish <br/>
### Contributors
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
## Translations
We use [Weblate](https://weblate.org) for translations. To get started, please visit the [project](https://hosted.weblate.org/projects/mue/) and look for the latest version to start translating Mue into your langauge.
## Attribution
[Pexels](https://pexels.com), [Unsplash](https://unsplash.com) - Stock photos used for offline mode <br/>
[Undraw](https://undraw.co) - Welcome modal images

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

BIN
assets/mue_readme.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

61
build/finalise.js Normal file
View File

@@ -0,0 +1,61 @@
import fs from `node:fs`;
import ADMZip from 'adm-zip';
import * as pkg from '../package.json';
export default function finalise(isProd) {
return {
name: 'finalise',
writeBundle() {
if (isProd) {
// clean up
if (fs.existsSync('./extensions')) {
fs.rmSync('./extensions', { recursive: true });
}
// prettify and move i18n report
fs.writeFileSync(
'./i18n-fallback.json',
JSON.stringify(
JSON.parse(fs.readFileSync('./dist/i18n-fallback.json', 'utf8')),
null,
2,
),
);
fs.rmSync('./dist/i18n-fallback.json');
for (const browser of ['chrome', 'firefox']) {
// set up
fs.mkdirSync(`./extensions/${browser}`, { recursive: true });
// copy manifest
fs.copyFileSync(
`./manifest/${browser}.json`,
`./extensions/${browser}/manifest.json`,
);
// copy service worker
fs.copyFileSync(
'./manifest/background.js',
`./extensions/${browser}/background.js`,
);
// chrome is weird
if (browser === `${browser}`) {
fs.cpSync(
'./manifest/_locales',
`./extensions/${browser}/_locales`,
{
recursive: true,
},
);
}
// copy build
fs.cpSync('./dist', `./extensions/${browser}/`, {
recursive: true,
});
// package
const cZip = new ADMZip();
cZip.addLocalFolder(`./extensions/${browser}`);
cZip.writeZip(`./extensions/${browser}-${pkg.version}.zip`);
}
}
},
}
}

1
build/i18n.js Normal file
View File

@@ -0,0 +1 @@
// https://hosted.weblate.org/api/components/mue/mue-tab/statistics/

BIN
bun.lockb Executable file

Binary file not shown.

16
cypress.config.js Normal file
View File

@@ -0,0 +1,16 @@
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
component: {
devServer: {
framework: "react",
bundler: "vite",
},
},
});

View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

5
cypress/e2e/date.cy.js Normal file
View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

5
cypress/e2e/navbar.cy.js Normal file
View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

5
cypress/e2e/quote.cy.js Normal file
View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

5
cypress/e2e/search.cy.js Normal file
View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

5
cypress/e2e/stats.cy.js Normal file
View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

5
cypress/e2e/time.cy.js Normal file
View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

View File

@@ -0,0 +1,5 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
})
})

200
cypress/e2e/welcome.cy.js Normal file
View File

@@ -0,0 +1,200 @@
/* eslint-disable no-undef */
describe('initial modal open', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeContent').should('be.visible')
})
})
describe('discord link', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeNotice a').eq(0).invoke('removeAttr', 'target').click()
cy.url().then((url) => {
expect(url).to.include('discord.com')
})
})
})
describe('contribute link', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeNotice a').eq(1).invoke('removeAttr', 'target').click()
cy.url().then(url => {
expect(url).to.include('github.com')
})
})
})
describe('preview function enable/disable', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
// does the preview button exist?
cy.get('.welcomeButtons button').eq(0).click()
// did preview load correctly?
cy.get('.preview-mode').should('be.visible')
// go back
cy.get('.preview-mode button').click()
// are we back?
cy.get('.welcomeContent').should('be.visible')
})
})
describe('second tab navigation', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
// are we on the second tab?
cy.get('.languageSettings').should('be.visible')
})
})
describe('change to each language setting and back', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
// change to each language setting
cy.get('.languageSettings span').each(($el, index, $list) => {
// press the next one
cy.get('.languageSettings span').eq(index).click()
// is it checked? state=checked
cy.get('.languageSettings span').eq(index).should('have.attr', 'state', 'checked')
})
})
})
describe('third tab navigation', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
// go to second
cy.get('.welcomeButtons button').eq(1).click()
// go to third
cy.get('.welcomeButtons button').eq(1).click()
})
})
describe('import settings', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
})
})
describe('fourth tab navigation', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
})
})
describe('theme change', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
})
})
describe('fifth tab navigation', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
})
})
describe('style choice', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
})
})
describe('sixth tab navigation', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
})
})
describe('offline mode check', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
})
})
describe('privacy policy link', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeNotice a').eq(2).invoke('removeAttr', 'target').click()
cy.url().then(url => {
expect(url).to.include('github.com')
})
})
})
describe('source code link', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeNotice a').eq(2).invoke('removeAttr', 'target').click()
cy.url().then(url => {
expect(url).to.include('github.com')
})
})
})
describe('final tab navigation', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
})
})
// describe the changes list
describe('finish button', () => {
it('passes', () => {
cy.visit('http://localhost:5173')
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(1).click()
cy.get('.welcomeButtons button').eq(2).click()
})
})

View File

@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>

View File

@@ -0,0 +1,24 @@
// ***********************************************************
// This example support/component.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
import { mount } from 'cypress/react18'
Cypress.Commands.add('mount', mount)
// Example use:
// cy.mount(<MyComponent />)

17
cypress/support/e2e.js Normal file
View File

@@ -0,0 +1,17 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'

View File

@@ -3,8 +3,8 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/png" sizes="32x32" href="/src/assets/icons/32x32.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/src/assets/icons/16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/icons/32x32.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/icons/16x16.png" />
<title>New Tab</title>
</head>

View File

@@ -4,7 +4,7 @@
"default_locale": "en",
"name": "__MSG_name__",
"description": "__MSG_description__",
"version": "7.1.2",
"version": "8.0.0",
"homepage_url": "https://muetab.com",
"action": {
"default_icon": "icons/128x128.png"

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for modern browsers.",
"version": "7.1.2",
"version": "8.0.0",
"homepage_url": "https://muetab.com",
"action": {
"default_icon": "icons/128x128.png"
@@ -17,5 +17,10 @@
},
"chrome_settings_overrides": {
"homepage": "index.html"
},
"browser_specific_settings": {
"gecko": {
"id": "{ac143a20-4b61-4c81-abdd-4bff77032972}"
}
}
}

66
migrate-translations.js Normal file
View File

@@ -0,0 +1,66 @@
const fs = require('fs');
const YAML = require('yaml');
const compareAndRemoveKeys = (json1, json2) => {
for (let key in json1) {
if (json2.hasOwnProperty(key)) {
if (typeof json1[key] === 'object' && typeof json2[key] === 'object') {
compareAndRemoveKeys(json1[key], json2[key]);
} else {
if (json1[key] === json2[key]) {
delete json1[key];
}
}
} else {
delete json1[key];
}
}
};
const original = JSON.parse(fs.readFileSync(`./src/i18n/locales/en-GB.json`, 'utf8'));
fs.readdirSync('./src/i18n/locales').forEach((e) => {
if (!e.endsWith('json')) return;
const data = JSON.parse(fs.readFileSync(`./src/i18n/locales/${e}`, 'utf8'));
const name = e.replace('.json', '');
if (name !== 'en-GB') {
compareAndRemoveKeys(data, original);
}
try {
fs.mkdirSync(`./src/i18n/${name}`);
} catch (e) {}
const _addons = YAML.stringify(data.modals?.main?.addons) || '{}';
fs.writeFileSync(`./src/i18n/${name}/_addons.yml`, _addons);
delete data?.modals?.main?.addons;
const _marketplace = YAML.stringify(data.modals?.main?.marketplace) || '{}';
fs.writeFileSync(`./src/i18n/${name}/_marketplace.yml`, _marketplace);
delete data?.modals?.main?.marketplace;
const _settings = YAML.stringify(data.modals?.main?.settings) || '{}';
fs.writeFileSync(`./src/i18n/${name}/_settings.yml`, _settings);
delete data?.modals?.main?.settings;
const _welcome = YAML.stringify(data.modals?.welcome) || '{}';
fs.writeFileSync(`./src/i18n/${name}/_welcome.yml`, _welcome);
delete data?.modals?.welcome;
const main = YAML.stringify(data) || '{}';
fs.writeFileSync(`./src/i18n/${name}/main.yml`, main);
});
fs.readdirSync('./src/i18n/locales/achievements').forEach((e) => {
if (!e.endsWith('json')) return;
const data = JSON.parse(fs.readFileSync(`./src/i18n/locales/achievements/${e}`, 'utf8'));
const name = e.replace('.json', '');
if (name !== 'en-GB') {
compareAndRemoveKeys(data, original);
}
const _achievements = YAML.stringify(data) || '{}';
fs.writeFileSync(`./src/i18n/${name}/_achievements.yml`, _achievements);
});

View File

@@ -9,56 +9,69 @@
"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": "7.1.2",
"version": "8.0.0",
"dependencies": {
"@eartharoid/i18n": "1.2.1",
"@eartharoid/i18n": "2.0.0-alpha.1",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@floating-ui/react-dom": "2.1.1",
"@fontsource/lexend-deca": "5.0.14",
"@fontsource/montserrat": "5.0.19",
"@floating-ui/react-dom": "2.1.0",
"@fontsource-variable/lexend-deca": "^5.1.0",
"@fontsource-variable/montserrat": "^5.1.0",
"@headlessui/react": "^2.1.9",
"@muetab/react-sortable-hoc": "^2.0.1",
"@mui/material": "6.0.2",
"@sentry/react": "^8.28.0",
"embla-carousel-autoplay": "8.2.1",
"embla-carousel-react": "8.2.1",
"@mui/material": "5.15.19",
"@sentry/react": "^8.33.1",
"clsx": "^2.1.1",
"embla-carousel-autoplay": "8.1.3",
"embla-carousel-react": "8.1.3",
"fast-blurhash": "^1.1.4",
"image-conversion": "^2.1.1",
"framer-motion": "^11.11.0",
"markdown-to-jsx": "^7.5.0",
"mue": "file:",
"react": "^18.3.1",
"react-best-gradient-color-picker": "^3.0.10",
"react-clock": "5.0.0",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-modal": "3.16.1",
"react-slider": "^2.0.6",
"react-toastify": "10.0.5",
"recharts": "^2.13.3",
"use-debounce": "^10.0.3"
},
"devDependencies": {
"@commitlint/cli": "^19.4.1",
"@commitlint/config-conventional": "^19.4.1",
"@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0",
"@eartharoid/deep-merge": "^0.0.2",
"@vitejs/plugin-react-swc": "^3.7.0",
"adm-zip": "0.5.16",
"eslint": "^8.57.0",
"@eartharoid/vite-plugin-i18n": "1.0.0-alpha.7",
"@tailwindcss/typography": "^0.5.15",
"@vitejs/plugin-react-swc": "^3.7.1",
"adm-zip": "^0.5.16",
"autoprefixer": "^10.4.20",
"cypress": "^13.17.0",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-config-react-app": "^7.0.1",
"husky": "^9.1.5",
"husky": "^9.1.6",
"prettier": "^3.3.3",
"sass": "^1.78.0",
"sass": "^1.79.4",
"stylelint": "^16.9.0",
"stylelint-config-standard-scss": "^13.1.0",
"stylelint-scss": "^6.5.1",
"vite": "5.4.3",
"vite-plugin-progress": "^0.0.7"
"stylelint-scss": "^6.7.0",
"tailwindcss": "^3.4.13",
"vite": "5.2.12",
"vite-plugin-inspect": "^0.8.7",
"vite-plugin-progress": "^0.0.7",
"yaml": "^2.5.1"
},
"scripts": {
"build": "vite build",
"cy:open": "cypress open",
"dev": "vite",
"dev:host": "vite --host",
"translations": "cd scripts && node updatetranslations.js",
"build": "vite build",
"pretty": "prettier --write \"./**/*.{js,jsx,json,scss,css}\"",
"lint": "eslint \"./src/**/*.{js,jsx}\" && stylelint \"./src/**/*.{scss,css}\"",
"lint:fix": "eslint \"./src/**/*.{js,jsx}\" --fix && stylelint \"./src/**/*.{scss,css}\" --fix",
"postinstall": "husky"
"postinstall": "husky",
"pretty": "prettier --write \"./**/*.{js,jsx,json,scss,css}\""
}
}

6548
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 804 B

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 308 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 274 KiB

View File

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB

View File

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 157 KiB

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View File

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 KiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -1,85 +0,0 @@
const fs = require('fs');
const path = require('path');
const merge = require('@eartharoid/deep-merge');
const compareAndRemoveKeys = (json1, json2) => {
for (let key in json1) {
if (json2.hasOwnProperty(key)) {
if (typeof json1[key] === 'object' && typeof json2[key] === 'object') {
compareAndRemoveKeys(json1[key], json2[key]);
}
} else {
delete json1[key];
}
}
};
const localesDir = path.join(__dirname, '../src/i18n/locales');
const achievementsDir = path.join(localesDir, 'achievements');
// Check if the locales directory exists, if not, create it
if (!fs.existsSync(localesDir)) {
fs.mkdirSync(localesDir, { recursive: true });
}
// Check if the achievements directory exists, if not, create it
if (!fs.existsSync(achievementsDir)) {
fs.mkdirSync(achievementsDir, { recursive: true });
}
fs.readdirSync(localesDir).forEach((file) => {
if (file === 'en_GB.json') {
return;
}
if (fs.lstatSync(path.join(localesDir, file)).isDirectory()) {
return;
}
const en = require(path.join(localesDir, 'en_GB.json'));
const newdata = merge(en, require(path.join(localesDir, file)));
compareAndRemoveKeys(newdata, en);
fs.writeFileSync(path.join(localesDir, file), JSON.stringify(newdata, null, 2));
fs.appendFileSync(path.join(localesDir, file), '\n');
});
fs.readdirSync(achievementsDir).forEach((file) => {
if (file === 'en_GB.json') {
return;
}
if (fs.lstatSync(path.join(achievementsDir, file)).isDirectory()) {
return;
}
const enGBFilePath = path.join(achievementsDir, 'en_GB.json');
if (!fs.existsSync(enGBFilePath)) {
console.error(`File 'en_GB.json' does not exist in the directory '${achievementsDir}'`);
return;
}
const en = require(enGBFilePath);
const newdata = merge(en, require(path.join(achievementsDir, file)));
compareAndRemoveKeys(newdata, en);
fs.writeFileSync(path.join(achievementsDir, file), JSON.stringify(newdata, null, 2));
fs.appendFileSync(path.join(achievementsDir, file), '\n');
const locales = fs.readdirSync(localesDir);
locales.forEach((locale) => {
if (!fs.existsSync(path.join(achievementsDir, locale))) {
// ignore directories
if (fs.lstatSync(path.join(localesDir, locale)).isDirectory()) {
return;
}
fs.writeFileSync(path.join(achievementsDir, locale), JSON.stringify(en, null, 2));
fs.appendFileSync(path.join(achievementsDir, locale), '\n');
}
});
});

View File

@@ -3,20 +3,22 @@ import { ToastContainer } from 'react-toastify';
import Background from 'features/background/Background';
import Widgets from 'features/misc/views/Widgets';
import Modals from 'features/misc/modals/Modals';
import { loadSettings, moveSettings } from 'utils/settings';
import { loadSettings } from 'utils/settings';
import EventBus from 'utils/eventbus';
import variables from 'config/variables';
import Preview from 'features/helpers/preview/Preview';
import Stats from 'features/stats/api/stats';
import Welcome from 'features/welcome/Welcome';
import BackgroundDefaults from 'features/background/options/default';
import defaults from 'config/default';
import '@fontsource-variable/lexend-deca';
import '@fontsource-variable/montserrat';
const useAppSetup = () => {
useEffect(() => {
const firstRun = localStorage.getItem('firstRun');
const stats = localStorage.getItem('stats');
if (!firstRun || !stats) {
moveSettings();
window.location.reload();
}
loadSettings();
const refreshHandler = (data) => {
@@ -27,8 +29,6 @@ const useAppSetup = () => {
EventBus.on('refresh', refreshHandler);
variables.stats.tabLoad();
return () => {
EventBus.off('refresh', refreshHandler);
};
@@ -40,20 +40,29 @@ const App = () => {
const [showBackground, setShowBackground] = useState(false);
useEffect(() => {
const storedToastDisplayTime = localStorage.getItem('toastDisplayTime');
const storedBackground = localStorage.getItem('background');
const storedToastDisplayTime =
localStorage.getItem('toastDisplayTime') || defaults.toastDisplayTime;
const storedBackground = localStorage.getItem('background') || BackgroundDefaults.background;
if (storedToastDisplayTime) {
setToastDisplayTime(parseInt(storedToastDisplayTime, 10));
}
if (storedBackground === 'true') {
if (storedBackground === 'true' || storedBackground === true) {
setShowBackground(true);
}
// Reset tab ID when component mounts and post initial event
Stats.generateTabId();
Stats.postEvent('new-tab', 'tab', 'opened');
}, []);
useAppSetup();
if (localStorage.getItem('showWelcome') !== 'false') {
return <Welcome />;
}
return (
<>
{showBackground && <Background />}
@@ -68,6 +77,9 @@ const App = () => {
<Widgets />
<Modals />
</div>
{localStorage.getItem('welcomePreview') === 'true' && (
<Preview setup={() => window.location.reload()} />
)}
</>
);
};

View File

@@ -1,10 +1,9 @@
import variables from 'config/variables';
import { useState, memo } from 'react';
import { TextareaAutosize } from '@mui/material';
import { MdAddLink, MdClose } from 'react-icons/md';
import { Tooltip } from 'components/Elements';
import { Button } from 'components/Elements';
import { Tooltip, Button } from 'components/Elements';
import { TextareaAutosize } from 'components/Form';
function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, editLink }) {
const [name, setName] = useState(edit ? editData.name : '');
@@ -19,7 +18,7 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
? variables.getMessage('widgets.quicklinks.edit')
: variables.getMessage('widgets.quicklinks.new')}
</span>
<Tooltip title={variables.getMessage('modals.welcome.buttons.close')}>
<Tooltip title={variables.getMessage('welcome:buttons.close')}>
<div className="close" onClick={() => closeModal()}>
<MdClose />
</div>
@@ -56,7 +55,7 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
type="settings"
onClick={() => editLink(editData, name, url, icon)}
icon={<MdAddLink />}
label={variables.getMessage('modals.main.settings.sections.quicklinks.edit')}
label={variables.getMessage('settings:sections.quicklinks.edit')}
/>
) : (
<Button

View File

@@ -1,64 +1,90 @@
import variables from 'config/variables';
import { Suspense, lazy, useState, memo } from 'react';
import { MdClose } from 'react-icons/md';
import { memo, Suspense, lazy } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import './scss/index.scss';
import { Tooltip } from 'components/Elements';
import Navbar from './backend/TabNavbar';
import { TabProvider, useTab } from './backend/TabContext';
import { MarketplaceDataProvider } from 'features/marketplace/api/MarketplaceDataContext';
const Settings = lazy(() => import('../../../features/misc/views/Settings'));
const Addons = lazy(() => import('../../../features/misc/views/Addons'));
const Marketplace = lazy(() => import('../../../features/misc/views/Marketplace'));
const renderLoader = () => (
<div style={{ display: 'flex', width: '100%', minHeight: '100%' }}>
<div className="modalSidebar">
<span className="mainTitle">Mue</span>
</div>
<div className="modalTabContent">
<div className="emptyItems">
<div className="emptyMessage">
<div className="loaderHolder">
<div id="loader"></div>
<span className="subtitle">{variables.getMessage('modals.main.loading')}</span>
</div>
</div>
</div>
<div className="flex flex-col w-full h-[65vh] justify-center items-center">
<div className="loaderHolder">
<div id="loader"></div>
<span className="subtitle">{variables.getMessage('modals.main.loading')}</span>
</div>
</div>
);
function MainModal({ modalClose }) {
const [currentTab, setCurrentTab] = useState('settings');
const MainModalContent = ({ modalClose }) => {
const { activeTab, direction } = useTab();
const changeTab = (type) => {
setCurrentTab(type);
const variants = {
enter: (direction) => ({
x: direction > 0 ? '100%' : '-100%',
opacity: 0,
top: '80px',
position: 'absolute',
width: '100%',
}),
center: {
x: 0,
opacity: 1,
top: '80px',
position: 'absolute',
width: '100%',
},
exit: (direction) => ({
x: direction < 0 ? '100%' : '-100%',
opacity: 0,
top: '80px',
position: 'absolute',
width: '100%',
}),
};
const renderTab = () => {
switch (currentTab) {
switch (activeTab) {
case 'addons':
return <Addons changeTab={changeTab} />;
return <Addons />;
case 'marketplace':
return <Marketplace changeTab={changeTab} />;
return <Marketplace />;
default:
return <Settings changeTab={changeTab} />;
return <Settings />;
}
};
return (
<div className="frame">
<Tooltip
style={{ position: 'absolute', top: '1rem', right: '1rem' }}
title={variables.getMessage('modals.welcome.buttons.close')}
key="closeTooltip"
>
<span className="closeModal" onClick={modalClose}>
<MdClose />
</span>
</Tooltip>
<Suspense fallback={renderLoader()}>{renderTab()}</Suspense>
<div className="flex flex-col w-full min-w-full ">
<Navbar modalClose={modalClose} />
<AnimatePresence initial={false} custom={direction}>
<motion.div
key={activeTab}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{ type: 'tween', duration: 0.8 }}
className="flex w-full min-w-full overflow-y-auto"
>
<Suspense fallback={renderLoader()}>{renderTab()}</Suspense>
</motion.div>
</AnimatePresence>
</div>
);
}
};
const MainModal = ({ modalClose }) => (
<TabProvider>
<MarketplaceDataProvider>
<MainModalContent modalClose={modalClose} />
</MarketplaceDataProvider>
</TabProvider>
);
const MemoizedMainModal = memo(MainModal);
export { MemoizedMainModal as default, MemoizedMainModal as MainModal };

View File

@@ -21,41 +21,41 @@ import {
MdOutlineAssessment as Stats,
MdOutlineNewReleases as Changelog,
MdInfoOutline as About,
MdOutlineExtension as Added,
MdSpaceDashboard as Added,
MdAddCircleOutline as Create,
MdViewAgenda as Overview,
MdCollectionsBookmark as Collections,
} from 'react-icons/md';
const iconMapping = {
[variables.getMessage('modals.main.marketplace.product.overview')]: <Overview />,
[variables.getMessage('marketplace:product.overview')]: <Overview />,
[variables.getMessage('modals.main.navbar.settings')]: <Settings />,
[variables.getMessage('modals.main.navbar.addons')]: <Addons />,
[variables.getMessage('modals.main.navbar.marketplace')]: <Marketplace />,
[variables.getMessage('modals.main.settings.sections.appearance.navbar.title')]: <Navbar />,
[variables.getMessage('modals.main.settings.sections.greeting.title')]: <Greeting />,
[variables.getMessage('modals.main.settings.sections.time.title')]: <Time />,
[variables.getMessage('modals.main.settings.sections.quicklinks.title')]: <QuickLinks />,
[variables.getMessage('modals.main.settings.sections.quote.title')]: <Quote />,
[variables.getMessage('modals.main.settings.sections.date.title')]: <Date />,
[variables.getMessage('modals.main.settings.sections.message.title')]: <Message />,
[variables.getMessage('modals.main.settings.sections.background.title')]: <Background />,
[variables.getMessage('modals.main.settings.sections.search.title')]: <MdSearch />,
[variables.getMessage('modals.main.settings.sections.weather.title')]: <Weather />,
[variables.getMessage('modals.main.settings.sections.appearance.title')]: <Appearance />,
[variables.getMessage('modals.main.settings.sections.language.title')]: <Language />,
[variables.getMessage('modals.main.settings.sections.advanced.title')]: <Advanced />,
[variables.getMessage('modals.main.settings.sections.stats.title')]: <Stats />,
[variables.getMessage('modals.main.settings.sections.experimental.title')]: <Experimental />,
[variables.getMessage('modals.main.settings.sections.changelog.title')]: <Changelog />,
[variables.getMessage('modals.main.settings.sections.about.title')]: <About />,
[variables.getMessage('modals.main.addons.added')]: <Added />,
[variables.getMessage('modals.main.addons.create.title')]: <Create />,
[variables.getMessage('modals.main.marketplace.all')]: <Addons />,
[variables.getMessage('modals.main.marketplace.photo_packs')]: <Background />,
[variables.getMessage('modals.main.marketplace.quote_packs')]: <Quote />,
[variables.getMessage('modals.main.marketplace.preset_settings')]: <Advanced />,
[variables.getMessage('modals.main.marketplace.collections')]: <Collections />,
[variables.getMessage('settings:sections.appearance.navbar.title')]: <Navbar />,
[variables.getMessage('settings:sections.greeting.title')]: <Greeting />,
[variables.getMessage('settings:sections.time.title')]: <Time />,
[variables.getMessage('settings:sections.quicklinks.title')]: <QuickLinks />,
[variables.getMessage('settings:sections.quote.title')]: <Quote />,
[variables.getMessage('settings:sections.date.title')]: <Date />,
[variables.getMessage('settings:sections.message.title')]: <Message />,
[variables.getMessage('settings:sections.background.title')]: <Background />,
[variables.getMessage('settings:sections.search.title')]: <MdSearch />,
[variables.getMessage('settings:sections.weather.title')]: <Weather />,
[variables.getMessage('settings:sections.appearance.title')]: <Appearance />,
[variables.getMessage('settings:sections.language.title')]: <Language />,
[variables.getMessage('settings:sections.advanced.title')]: <Advanced />,
[variables.getMessage('settings:sections.stats.title')]: <Stats />,
[variables.getMessage('settings:sections.experimental.title')]: <Experimental />,
[variables.getMessage('settings:sections.changelog.title')]: <Changelog />,
[variables.getMessage('settings:sections.about.title')]: <About />,
[variables.getMessage('addons:added')]: <Added />,
[variables.getMessage('addons:create.title')]: <Create />,
[variables.getMessage('marketplace:all')]: <Addons />,
[variables.getMessage('marketplace:photo_packs')]: <Background />,
[variables.getMessage('marketplace:quote_packs')]: <Quote />,
[variables.getMessage('marketplace:preset_settings')]: <Advanced />,
[variables.getMessage('marketplace:collections')]: <Collections />,
};
function Tab({ label, currentTab, onClick, navbarTab }) {
@@ -71,34 +71,15 @@ function Tab({ label, currentTab, onClick, navbarTab }) {
}
const icon = iconMapping[label];
const divider = [
variables.getMessage('modals.main.settings.sections.weather.title'),
variables.getMessage('modals.main.settings.sections.language.title'),
variables.getMessage('modals.main.marketplace.all'),
variables.getMessage('modals.main.settings.sections.experimental.title'),
].includes(label);
const mue = [
variables.getMessage('modals.main.marketplace.product.overview'),
variables.getMessage('modals.main.addons.added'),
variables.getMessage('modals.main.marketplace.all'),
].includes(label);
if (
label === variables.getMessage('modals.main.settings.sections.experimental.title') &&
!isExperimental
) {
return <hr />;
if (label === variables.getMessage('settings:sections.experimental.title') && !isExperimental) {
return null;
}
return (
<>
{mue && <span className="mainTitle">Mue</span>}
<button className={className} onClick={() => onClick(label)}>
{icon} <span>{label}</span>
</button>
{divider && <hr />}
</>
<button className={className} onClick={() => onClick(label)}>
{icon} <span>{label}</span>
</button>
);
}

View File

@@ -0,0 +1,56 @@
import { createContext, useContext, useState } from 'react';
import variables from 'config/variables';
const TabContext = createContext();
export const useTab = () => {
return useContext(TabContext);
};
export const TabProvider = ({ children }) => {
const [activeTab, setActiveTab] = useState('settings');
const [subTab, setSubTab] = useState(variables.getMessage('marketplace:product.overview'));
const [subSection, setSubSection] = useState('');
const [direction, setDirection] = useState(1);
const changeTab = (tab, subtab = '', section = '') => {
const tabs = [
{ id: 'settings', label: 'Settings' },
{ id: 'addons', label: 'Addons' },
{ id: 'marketplace', label: 'Marketplace' },
];
const currentIndex = tabs.findIndex((t) => t.id === activeTab);
const newIndex = tabs.findIndex((t) => t.id === tab);
setDirection(newIndex > currentIndex ? 1 : -1);
setSubTab(subtab);
if (tab === 'settings' && subtab === '' && section === '') {
setSubTab(variables.getMessage('marketplace:product.overview'));
}
setActiveTab(tab);
setSubSection(section);
};
const setSection = (type) => {
setSubTab(type);
};
return (
<TabContext.Provider
value={{
activeTab,
subTab,
direction,
subSection,
changeTab,
setSubTab,
setSection,
setSubSection,
}}
>
{children}
</TabContext.Provider>
);
};

View File

@@ -0,0 +1,275 @@
import React from 'react';
import {
MdSettings,
MdOutlineShoppingBasket,
MdSpaceDashboard,
MdOutlineKeyboardArrowRight,
MdClose,
MdSearch,
} from 'react-icons/md';
import { IoMdPricetag } from 'react-icons/io';
import { motion, AnimatePresence } from 'framer-motion';
import { useTab } from './TabContext';
import { useMarketData } from 'features/marketplace/api/MarketplaceDataContext';
import { Tooltip } from 'components/Elements';
import variables from 'config/variables';
import clsx from 'clsx';
const TabNavbar = ({ modalClose }) => {
const { activeTab, subTab, changeTab, subSection, setSubTab, setSubSection } = useTab();
const { setSelectedItem, setSelectedCollection, installedItems } = useMarketData();
const tabs = [
{ id: 'settings', label: 'Settings', icon: <MdSettings /> },
{ id: 'addons', label: 'Addons', icon: <MdSpaceDashboard /> },
{ id: 'marketplace', label: 'Marketplace', icon: <IoMdPricetag /> },
];
const navbarLogo = (
<svg
width="123"
height="123"
viewBox="0 0 123 123"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="w-[40px] h-[40px]"
>
<g filter="url(#filter0_d_2473_27)">
<circle cx="61.5" cy="61.5" r="50.5" fill="url(#paint0_linear_2473_27)" />
<path
d="M68.2969 43.1796V48.5603H79.9348V60.1055H85.3638V43.1796H68.2969Z"
fill="url(#paint1_linear_2473_27)"
/>
<path
d="M72.1542 61.0483H67.344V65.8527H62.9056V61.0483H58.0919V56.6185H62.9056V51.8175H67.344V56.6185H72.1542V61.0483ZM78.6447 49.6043H67.034V45.5766H47.5625V72.0938H82.6836V61.1961H78.6447V49.6043Z"
fill="url(#paint2_linear_2473_27)"
/>
<path
d="M46.358 50.518H42.6289V77.0352H77.75V73.3029H46.358V50.518Z"
fill="url(#paint3_linear_2473_27)"
/>
<path
d="M41.4205 55.4516H37.6914V81.9688H72.8125V78.2365H41.4205V55.4516Z"
fill="url(#paint4_linear_2473_27)"
/>
</g>
<defs>
<filter
id="filter0_d_2473_27"
x="0.3"
y="0.3"
width="122.4"
height="122.4"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
/>
<feOffset />
<feGaussianBlur stdDeviation="5.35" />
<feComposite in2="hardAlpha" operator="out" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2473_27" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_2473_27"
result="shape"
/>
</filter>
<linearGradient
id="paint0_linear_2473_27"
x1="104.324"
y1="35.24"
x2="16.959"
y2="88.366"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#FF5C25" />
<stop offset="0.484375" stopColor="#D21A11" />
<stop offset="1" stopColor="#FF456E" />
</linearGradient>
<linearGradient
id="paint1_linear_2473_27"
x1="76.8303"
y1="60.1055"
x2="76.8303"
y2="43.1796"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F18D91" />
<stop offset="1" stopColor="#FBD3C6" />
</linearGradient>
<linearGradient
id="paint2_linear_2473_27"
x1="65.123"
y1="72.0938"
x2="65.123"
y2="45.5766"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F18D91" />
<stop offset="1" stopColor="#FBD3C6" />
</linearGradient>
<linearGradient
id="paint3_linear_2473_27"
x1="60.1895"
y1="77.0352"
x2="60.1895"
y2="50.518"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F18D91" />
<stop offset="1" stopColor="#FBD3C6" />
</linearGradient>
<linearGradient
id="paint4_linear_2473_27"
x1="55.252"
y1="81.9688"
x2="55.252"
y2="55.4516"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F18D91" />
<stop offset="1" stopColor="#FBD3C6" />
</linearGradient>
</defs>
</svg>
);
return (
<div className="flex flex-row gap-5 p-5 items-center justify-between">
<div className="flex flex-row gap-5 items-center">
{navbarLogo}
<div className="flex flex-row items-center gap-2">
<span
onClick={() => {
changeTab(activeTab);
setSelectedItem(null);
setSelectedCollection(null);
}}
className={clsx(
'text-xl capitalize tracking-normal transition-all duration-150 ease-in-out',
{
'text-neutral-300 cursor-pointer hover:text-neutral-100':
subTab !== '' && (activeTab === 'marketplace' || activeTab === 'addons'),
},
)}
>
{variables.getMessage(`modals.main.navbar.${activeTab}`)}
</span>
{subTab !== '' && (
<>
<MdOutlineKeyboardArrowRight />
<span
onClick={() => setSubSection('')}
className={clsx(
'text-xl capitalize tracking-normal transition-all duration-150 ease-in-out',
{
'dark:text-neutral-300 text-neutral-600 cursor-pointer hover:text-black dark:hover:text-neutral-100':
subSection !== '',
},
)}
>
{subTab}
</span>
</>
)}
{subSection !== '' && (
<>
<MdOutlineKeyboardArrowRight />
<span className="text-xl capitalize tracking-normal">{subSection}</span>
</>
)}
</div>
</div>
<div className="flex flex-row gap-5">
<AnimatePresence>
{activeTab === 'marketplace' && subTab === '' && (
<motion.div
initial={{ opacity: 0, y: '-100%' }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: '-100%' }}
>
<form className="max-w-md mx-auto relative mr-10">
<input
label={variables.getMessage('widgets.search')}
placeholder={variables.getMessage('widgets.search')}
name="filter"
id="filter"
className="h-[40px] block w-full px-4 ps-10 text-sm text-gray-900 border border-[#484848] rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-white/5 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-neutral-100"
/>
<div className="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
<MdSearch />
</div>
</form>
</motion.div>
)}
</AnimatePresence>
<div className="flex space-x-1">
{tabs.map((tab) => (
<button
key={tab.id}
onClick={() => {
changeTab(tab.id);
setSelectedItem(null);
setSelectedCollection(null);
}}
className={`${
activeTab === tab.id ? '' : 'dark:hover:text-white/70 hover:text-black/70'
} dark:text-white text-black transition-all duration-800 ease-in-out flex flex-row gap-2 items-center relative rounded-sm px-3 py-1.5 text-sm outline-sky-400 transition focus-visible:outline-2`}
style={{
WebkitTapHighlightColor: 'transparent',
}}
>
{activeTab === tab.id && (
<motion.span
layoutId="tabNavbarBubble"
className="absolute inset-0 z-10 bg-[#333] mix-blend-lighten rounded-xl"
transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }}
/>
)}
{tab.icon}
{variables.getMessage(`modals.main.navbar.${tab.id}`)}
{tab.id === 'addons' && (
<AnimatePresence>
<div className="px-3 py-1 dark:bg-[#424242] bg-neutral-300 rounded-lg text-xs">
<motion.span
key={installedItems.length}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
>
{installedItems.length}
</motion.span>
</div>
</AnimatePresence>
)}
{tab.id === 'marketplace' && (
<span className="px-3 py-1 bg-rose-800 rounded-lg text-xs border border-rose-700 text-white">
NEW
</span>
)}
</button>
))}
</div>
<Tooltip
style={{ marginLeft: 'auto', justifySelf: 'flex-end' }}
title={variables.getMessage('welcome:buttons.close')}
key="closeTooltip"
>
<span className="closeModal" onClick={modalClose}>
<MdClose />
</span>
</Tooltip>
</div>
</div>
);
};
export { TabNavbar as default, TabNavbar };

View File

@@ -1,109 +0,0 @@
import variables from 'config/variables';
import React, { useState, useEffect } from 'react';
import {
MdSettings,
MdOutlineShoppingBasket,
MdOutlineExtension,
MdRefresh,
MdClose,
} from 'react-icons/md';
import Tab from './Tab';
import { Button } from 'components/Elements';
import ErrorBoundary from '../../../../features/misc/modals/ErrorBoundary';
const Tabs = (props) => {
const [currentTab, setCurrentTab] = useState(props.children[0].props.label);
const [currentName, setCurrentName] = useState(props.children[0].props.name);
const onClick = (tab, name) => {
if (name !== currentName) {
variables.stats.postEvent('tab', `Opened ${name}`);
}
setCurrentTab(tab);
setCurrentName(name);
};
const hideReminder = () => {
localStorage.setItem('showReminder', false);
document.querySelector('.reminder-info').style.display = 'none';
};
const navbarButtons = [
{
tab: 'settings',
icon: <MdSettings />,
},
{
tab: 'addons',
icon: <MdOutlineExtension />,
},
{
tab: 'marketplace',
icon: <MdOutlineShoppingBasket />,
},
];
const reminderInfo = (
<div
className="reminder-info"
style={{ display: localStorage.getItem('showReminder') === 'true' ? 'flex' : 'none' }}
>
<div className="shareHeader">
<span className="title">{variables.getMessage('modals.main.settings.reminder.title')}</span>
<span className="closeModal" onClick={hideReminder}>
<MdClose />
</span>
</div>
<span className="subtitle">
{variables.getMessage('modals.main.settings.reminder.message')}
</span>
<button onClick={() => window.location.reload()}>
<MdRefresh />
{variables.getMessage('modals.main.error_boundary.refresh')}
</button>
</div>
);
return (
<div style={{ display: 'flex', width: '100%', minHeight: '100%' }}>
<div className="modalSidebar">
{props.children.map((tab, index) => (
<Tab
currentTab={currentTab}
key={index}
label={tab.props.label}
onClick={(nextTab) => onClick(nextTab, tab.props.name)}
navbarTab={props.navbar || false}
/>
))}
{reminderInfo}
</div>
<div className="modalTabContent">
<div className="modalNavbar">
{navbarButtons.map(({ tab, icon }, index) => (
<Button
type="navigation"
onClick={() => props.changeTab(tab)}
icon={icon}
label={variables.getMessage(`modals.main.navbar.${tab}`)}
active={props.current === tab}
key={`${tab}-${index}`}
/>
))}
</div>
{props.children.map((tab, index) => {
if (tab.props.label !== currentTab) {
return undefined;
}
return (
<ErrorBoundary key={`error-boundary-${index}`}>{tab.props.children}</ErrorBoundary>
);
})}
</div>
</div>
);
};
export default Tabs;

View File

@@ -0,0 +1,107 @@
import { useState, useCallback, memo, useMemo } from 'react';
import variables from 'config/variables';
import Tab from './Tab';
import { useTab } from './TabContext';
import { MdOutlineWarning, MdRefresh, MdClose } from 'react-icons/md';
import Stats from 'features/stats/api/stats';
const Sidebar = memo(({ sections, currentTab, setCurrentTab }) => {
const { subTab, setSubTab, setSubSection } = useTab();
const handleClick = useCallback(
(label) => () => {
const newTab = variables.getMessage(label);
setSubTab(newTab);
setSubSection('');
Stats.postEvent('settings-tab', newTab, 'opened');
},
[setSubTab, setSubSection],
);
const hideReminder = () => {
localStorage.setItem('showReminder', false);
document.querySelector('.reminder-info').style.display = 'none';
};
const reminderInfo = useMemo(
() => (
<div
className="bg-rose-800 border-rose-700 border-2 flex-row px-10 py-5 rounded items-center justify-between"
style={{ display: localStorage.getItem('showReminder') === 'true' ? 'flex' : 'none' }}
>
<div className="flex flex-row items-center gap-5">
<MdOutlineWarning />
<span>{variables.getMessage('settings:reminder.message')}</span>
</div>
<div className="flex flex-row items-center gap-5">
<button
className="bg-neutral-900 border-neutral-800 border-2 px-8 py-2 flex flex-row items-center gap-2 rounded"
onClick={() => window.location.reload()}
>
<MdRefresh /> {variables.getMessage('modals.main.error_boundary.refresh')}
</button>
<button
className="bg-neutral-900 border-neutral-800 border-2 px-8 py-2 flex flex-row items-center gap-2 rounded"
onClick={hideReminder}
>
<MdClose />
Close
</button>
</div>
</div>
),
[],
);
return (
<div className="modalSidebar">
{sections.map((section, index) => (
<Tab
key={index}
currentTab={subTab}
label={variables.getMessage(section.label)}
onClick={handleClick(section.label)}
navbarTab={section.navbar || false}
/>
))}
{reminderInfo}
</div>
);
});
const Content = memo(({ sections, currentTab }) => {
const hideReminder = () => {
localStorage.setItem('showReminder', false);
document.querySelector('.reminder-info').style.display = 'none';
};
return (
<>
{sections.map(
({ label, name, component: Component }) =>
variables.getMessage(label) === currentTab && (
<div
className="w-full rounded h-[calc(78vh-80px)] flex flex-col pr-10 gap-3 lg:overflow-x-hidden overflow-y-auto overflow-x-auto"
key={name}
label={variables.getMessage(label)}
name={name}
>
<Component />
</div>
),
)}
</>
);
});
const Tabs = ({ sections }) => {
const { subTab, setSubTab, setSubSection } = useTab();
return (
<div className="flex flex-row w-full gap-2">
<Sidebar sections={sections} currentTab={subTab} />
<Content sections={sections} currentTab={subTab} />
</div>
);
};
export { Tabs };

View File

@@ -27,6 +27,7 @@
z-index: -2;
transition-timing-function: ease-in;
border-radius: map-get($modal, 'border-radius');
-webkit-user-select: none;
user-select: none;
overflow-y: auto;
transform: scale(0);
@@ -37,6 +38,7 @@
}
.modalInfoPage {
-webkit-user-select: text;
user-select: text;
}
}
@@ -47,13 +49,46 @@
right: 3rem;
}
.ReactModal__Html--open,
.ReactModal__Body--open {
overflow: hidden;
}
/* modal transition */
.ReactModal__Content--after-open {
opacity: 1;
transform: scale(1);
}
.ReactModal__Content--before-close {
opacity: 0;
transform: scale(0);
}
#modal {
height: 80vh;
width: clamp(60vw, 1400px, 90vw);
@include themed {
background-color: t($modal-background);
}
}
.closePositioning {
position: absolute;
top: 3rem;
right: 3rem;
}
.closeModal {
display: grid;
place-items: center;
padding: 0.5em;
height: 40px;
width: 40px;
border-radius: 12px;
cursor: pointer;
transition: 0.5s;
align-self: flex-end;
svg {
font-size: 2em;
@@ -82,15 +117,6 @@
transform: scale(0);
}
#modal {
height: 80vh;
width: clamp(60vw, 1400px, 90vw);
@include themed {
background-color: t($modal-background);
}
}
/* fixes for font size on extension */
label,
p,
@@ -124,9 +150,9 @@ h5 {
height: 50px;
@include themed {
border: 3px solid t($modal-sidebar);
border: 3px solid t($btn-background);
border-radius: 50%;
border-top-color: t($modal-sidebarActive);
border-top-color: t($brand-accent);
}
animation: spin 1s ease-in-out infinite;
@@ -247,13 +273,12 @@ h5 {
flex-flow: row;
justify-content: space-between;
padding: 25px;
margin-top: 20px;
transition: 0.5s;
@include themed {
background: t($modal-sidebar);
border-radius: t($borderRadius);
box-shadow: 0 0 0 1px t($modal-sidebarActive);
//box-shadow: 0 0 0 1px t($modal-sidebarActive);
&:hover {
background: t($modal-sidebarActive);
@@ -269,6 +294,7 @@ h5 {
flex-flow: row;
align-items: center;
gap: 25px;
flex-grow: 0;
svg {
@include themed {
@@ -291,14 +317,14 @@ h5 {
flex-flow: row;
gap: 20px;
align-items: center;
width: 275px;
justify-content: flex-end;
}
}
.reminder-info {
display: flex;
flex-flow: column;
position: absolute;
bottom: 0;
padding: 15px;
gap: 15px;

View File

@@ -51,31 +51,12 @@
@include themed {
background-color: t($modal-secondaryColour);
box-shadow: 0 0 0 1px t($modal-sidebarActive);
&:hover {
background-color: t($modal-sidebarActive);
img {
background-color: t($modal-sidebarActive);
}
}
}
.tags {
margin-top: 7px;
}
.item-back {
filter: blur(60px) saturate(180%) brightness(90%);
position: absolute;
object-fit: cover !important;
height: 90px;
width: 100px;
border-radius: 100px;
transition: 0.5s;
margin-top: 30px;
}
.item-icon {
object-fit: cover !important;
height: 60px !important;
@@ -125,15 +106,15 @@
}
.itemPage {
display: flex;
flex-flow: row;
justify-content: space-between;
// display: flex;
// flex-flow: row;
// justify-content: space-between;
.itemShowcase {
display: flex;
flex-flow: column;
gap: 25px;
width: 60%;
// width: 60%;
max-width: 650px;
.description {
@@ -162,31 +143,24 @@
border-radius: 15px;
width: 30%;
max-width: 300px;
max-height: 700px;
// max-height: 700px;
.front {
padding: 20px;
height: 100%;
display: flex;
flex-flow: column;
gap: 15px;
width: 100%;
box-sizing: border-box !important;
border-radius: 12px 12px 0 0;
backdrop-filter: blur(40px) saturate(150%) brightness(75%);
@include themed {
background-image: linear-gradient(to bottom, transparent, t($modal-background));
}
}
padding: 20px;
height: 100%;
display: flex;
flex-flow: column;
gap: 15px;
width: 100%;
box-sizing: border-box !important;
border-radius: 12px;
.icon {
width: 100%;
height: auto;
border-radius: 12px;
box-shadow: 0 5px 25px black;
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.75);
aspect-ratio: 1 / 1;
object-fit: contain;
object-fit: cover;
}
.divider {
@@ -435,35 +409,6 @@ p.author {
align-items: center;
}
.marketplaceSearch {
display: flex;
align-items: center;
padding: 10px 30px;
border-radius: 10px;
font-size: 18px;
@include themed {
box-shadow: 0 0 0 3px t($modal-sidebarActive);
background: t($modal-sidebar);
}
input {
all: unset;
}
@include themed {
&:focus-within {
background: t($modal-sidebarActive);
box-shadow: 0 0 0 1px t($color);
}
&:disabled {
background: t($modal-sidebarActive);
cursor: not-allowed;
}
}
}
.inCollection {
// background-image: linear-gradient(to left, transparent, #000),
// url('https://external-preview.redd.it/JyhsEoGMhKIMi3kvfBS24L0IllAO_KrIm4UI-dA1Ax4.jpg?auto=webp&s=b5adf9859b2c1855a5b3085f9453a6e878548505');
@@ -507,7 +452,6 @@ p.author {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15px;
.tooltip {
margin-right: 25px;

View File

@@ -9,9 +9,11 @@ p.description {
}
.moreInfo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
.details {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
}
.items {
margin-top: 0 !important;

View File

@@ -1,67 +1,43 @@
@import 'scss/variables';
.modalTabContent {
width: 100% !important;
.settingsRow {
display: flex;
align-items: center;
min-height: 100px;
justify-content: space-between;
transition: 0.4s ease-in-out;
@extend %tabText;
/* button {
@include modal-button(standard);
} */
/* border-top: 1px solid #ccc; */
border-bottom: 1px solid #676767;
padding-top: 1rem;
padding-bottom: 1rem;
@include themed {
padding: 1rem 3rem 3rem;
&.settingsNoBorder {
border-bottom: none;
}
.content {
display: flex;
flex-direction: column;
width: 100%;
background: t($modal-background);
flex-flow: column;
max-width: 50%;
}
@extend %tabText;
.action {
display: flex;
flex-flow: column;
align-items: flex-end;
width: 300px;
hr {
width: 100%;
background: rgb(196 196 196 / 74%);
outline: none;
button {
margin-top: 10px;
}
.settingsRow {
.link {
display: flex;
flex-flow: row;
gap: 15px;
align-items: center;
min-height: 100px;
justify-content: space-between;
transition: 0.4s ease-in-out;
/* border-top: 1px solid #ccc; */
border-bottom: 1px solid #676767;
padding-top: 1rem;
padding-bottom: 1rem;
&.settingsNoBorder {
border-bottom: none;
}
.content {
display: flex;
flex-flow: column;
max-width: 50%;
}
.action {
display: flex;
flex-flow: column;
align-items: flex-end;
width: 300px;
button {
margin-top: 10px;
}
.link {
margin-top: 10px;
display: flex;
flex-flow: row;
gap: 15px;
align-items: center;
}
}
}
}
}
@@ -81,60 +57,61 @@
padding: 5px 10px;
}
}
.itemPage {
table {
border-collapse: separate;
border-radius: 10px;
margin-top: 20px;
table {
border-collapse: separate;
border-radius: 10px;
margin-top: 20px;
@include themed {
box-shadow: 0 0 0 1px t($modal-sidebarActive);
padding: 0;
border: 0;
outline: none;
}
tr:first-child {
@include themed {
border-radius: t($borderRadius);
color: t($subColor);
box-shadow: 0 0 0 1px t($modal-sidebarActive);
padding: 0;
border: 0;
outline: none;
}
letter-spacing: 2px;
th {
padding: 20px;
}
}
td {
padding: 15px;
}
tr {
th:last-child {
display: grid;
place-items: center;
}
}
::placeholder {
@include themed {
color: t($subColor);
}
}
tr:not(:first-child) {
@include themed {
background: t($modal-secondaryColour);
}
textarea {
width: 90%;
margin: 10px;
tr:first-child {
@include themed {
color: t($color);
border-radius: t($borderRadius);
color: t($subColor);
}
letter-spacing: 2px;
th {
padding: 20px;
}
}
td {
padding: 15px;
}
tr {
th:last-child {
display: grid;
place-items: center;
}
}
::placeholder {
@include themed {
color: t($subColor);
}
}
tr:not(:first-child) {
@include themed {
background: t($modal-secondaryColour);
}
textarea {
width: 90%;
margin: 10px;
@include themed {
color: t($color);
}
}
}
}

View File

@@ -3,10 +3,3 @@
align-items: flex-start;
justify-content: flex-start;
}
.modalNavbar {
display: flex;
flex-flow: row;
gap: 25px;
margin-bottom: 1rem;
}

View File

@@ -7,10 +7,9 @@
position: sticky;
margin: 0;
padding: 0 5px;
background: t($modal-sidebar);
border-radius: 12px 0 0 12px;
overflow: hidden auto;
height: 80vh;
height: calc(80vh - 80px);
min-width: 250px;
.mainTitle {

View File

@@ -1,18 +1,3 @@
.updateChangelog {
max-width: 75%;
margin-top: 15px;
white-space: pre-wrap;
font-size: 18px;
a {
color: var(--modal-link);
&:hover {
opacity: 0.8;
}
}
}
.changelogtab {
.mainTitle {
margin: 0 !important;
@@ -22,6 +7,12 @@
max-width: 95%;
}
a {
&:hover {
opacity: 0.8;
}
}
.changelogAt {
text-decoration: none;
}

View File

@@ -42,6 +42,17 @@
-webkit-padding-start: 0;
padding: 0;
list-style-type: none;
margin-top: 16px;
}
.images-row.fixed-width {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 10px;
}
.image-container {
width: 200px;
}
.images-row {

View File

@@ -6,7 +6,7 @@ import { Tooltip, Button } from 'components/Elements';
function ResetModal({ modalClose }) {
const reset = () => {
variables.stats.postEvent('setting', 'Reset');
variables.stats.postEvent('setting', 'reset');
setDefaultSettings('reset');
window.location.reload();
};
@@ -15,34 +15,32 @@ function ResetModal({ modalClose }) {
<div className="smallModal">
<div className="shareHeader">
<span className="title">
{variables.getMessage('modals.main.settings.sections.advanced.reset_modal.title')}
{variables.getMessage('settings:sections.advanced.reset_modal.title')}
</span>
<Tooltip
title={variables.getMessage('modals.main.settings.sections.advanced.reset_modal.cancel')}
>
<Tooltip title={variables.getMessage('settings:sections.advanced.reset_modal.cancel')}>
<div className="close" onClick={modalClose}>
<MdClose />
</div>
</Tooltip>
</div>
<span className="title">
{variables.getMessage('modals.main.settings.sections.advanced.reset_modal.question')}
{variables.getMessage('settings:sections.advanced.reset_modal.question')}
</span>
<span className="subtitle">
{variables.getMessage('modals.main.settings.sections.advanced.reset_modal.information')}
{variables.getMessage('settings:sections.advanced.reset_modal.information')}
</span>
<div className="resetFooter">
<Button
type="secondary"
onClick={modalClose}
icon={<MdClose />}
label={variables.getMessage('modals.main.settings.sections.advanced.reset_modal.cancel')}
label={variables.getMessage('settings:sections.advanced.reset_modal.cancel')}
/>
<Button
type="settings"
onClick={() => reset()}
icon={<MdRestartAlt />}
label={variables.getMessage('modals.main.settings.buttons.reset')}
label={variables.getMessage('settings:buttons.reset')}
/>
</div>
</div>

View File

@@ -42,7 +42,7 @@ function ShareModal({ modalClose, data }) {
<div className="smallModal">
<div className="shareHeader">
<span className="title">{variables.getMessage('widgets.quote.share')}</span>
<Tooltip title={variables.getMessage('modals.welcome.buttons.close')}>
<Tooltip title={variables.getMessage('welcome:buttons.close')}>
<div className="close" onClick={modalClose}>
<MdClose />
</div>

View File

@@ -1,5 +1,6 @@
import { useState, memo, useRef } from 'react';
import { useFloating, flip, offset, shift } from '@floating-ui/react-dom';
import { motion, AnimatePresence } from 'framer-motion';
import './tooltip.scss';
function Tooltip({ children, title, style, placement, subtitle }) {
@@ -17,7 +18,7 @@ function Tooltip({ children, title, style, placement, subtitle }) {
return (
<>
<div
<motion.div
className="tooltip"
style={style}
onMouseEnter={() => setShowTooltip(true)}
@@ -26,25 +27,34 @@ function Tooltip({ children, title, style, placement, subtitle }) {
onBlur={() => setShowTooltip(false)}
ref={setReference}
aria-describedby={tooltipId.current}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.2 }}
>
{children}
</div>
{showTooltip && (
<span
ref={refs.setFloating}
style={{
position: strategy,
top: y ?? '',
left: x ?? '',
display: 'flex',
flexFlow: 'column',
}}
className="tooltipTitle"
>
{title}
<span style={{ fontSize: '8px' }}>{subtitle}</span>
</span>
)}
</motion.div>
<AnimatePresence>
{showTooltip && (
<motion.span
ref={refs.setFloating}
style={{
position: strategy,
top: y ?? '',
left: x ?? '',
display: 'flex',
flexFlow: 'column',
}}
className="tooltipTitle"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ duration: 0.2 }}
>
{title}
<span style={{ fontSize: '8px' }}>{subtitle}</span>
</motion.span>
)}
</AnimatePresence>
</>
);
}

View File

@@ -19,6 +19,7 @@
.tooltipTitle {
@extend %basic;
border-radius: 8px !important;
text-align: center;
font-size: 0.6rem;
@@ -33,9 +34,6 @@
cursor: initial;
user-select: none;
opacity: 1;
animation-name: floating;
animation-duration: 0.3s;
animation-timing-function: ease-in;
}
#modal {
@@ -54,26 +52,6 @@
}
}
.tooltipTitle::before {
transform: scale3d(0.2, 0.2, 1);
transition: all 0.2s ease-in-out;
}
.tooltipTitle::after {
transform: translate3d(0, 6px, 0);
transition: all 0.1s ease-in-out;
}
.tooltipTitle:hover::before,
.tooltipTitle:hover::after {
opacity: 1;
transform: scale3d(1, 1, 1);
}
.tooltipTitle:hover::after {
transition: all 0.2s 0.1s ease-in-out;
}
#arrow {
position: absolute;
background: #333;
@@ -96,37 +74,3 @@
}
}
}
#floating {
transition-property: opacity, transform;
}
#floating[data-status='open'],
#floating[data-status='close'] {
transition-duration: 250ms;
}
#floating[data-status='initial'],
#floating[data-status='close'] {
opacity: 0;
}
#floating[data-status='initial'][data-placement^='top'],
#floating[data-status='close'][data-placement^='top'] {
transform: translateY(5px);
}
#floating[data-status='initial'][data-placement^='bottom'],
#floating[data-status='close'][data-placement^='bottom'] {
transform: translateY(-5px);
}
#floating[data-status='initial'][data-placement^='left'],
#floating[data-status='close'][data-placement^='left'] {
transform: translateX(5px);
}
#floating[data-status='initial'][data-placement^='right'],
#floating[data-status='close'][data-placement^='right'] {
transform: translateX(-5px);
}

View File

@@ -0,0 +1,68 @@
/* eslint-disable no-undef */
import React from 'react'
import { Checkbox } from './Checkbox'
describe('<Checkbox />', () => {
it('renders', () => {
// see: https://on.cypress.io/mounting-react
cy.mount(<Checkbox />)
})
// checked prop works
it('can init checked', () => {
cy.mount(<Checkbox checked={true} />)
cy.get('span').should('have.attr', 'aria-checked', 'true')
})
it('can init unchecked', () => {
cy.mount(<Checkbox checked={false} />)
cy.get('span').should('have.attr', 'aria-checked', 'false')
})
// can init with setting
it('can init with setting', () => {
localStorage.setItem('test', 'true')
cy.mount(<Checkbox name="test" />)
cy.get('span').should('have.attr', 'aria-checked', 'true')
})
// can be changed
it('can be changed', () => {
cy.mount(<Checkbox checked={true} />)
cy.get('span').click().should('have.attr', 'aria-checked', 'false')
cy.get('span').click().should('have.attr', 'aria-checked', 'true')
})
// onChange callback works
it('calls onChange when clicked', () => {
const onChange = cy.stub()
cy.mount(<Checkbox onChange={onChange} />)
cy.get('span').click().then(() => {
expect(onChange).to.be.called()
})
})
// disabled prop works
// text prop works
it('displays text', () => {
cy.mount(<Checkbox text="Hello, world!" />)
cy.contains('Hello, world!').should('be.visible')
})
// reminder works (needs stub)
// reminder works (needs stub)
// category prop works (needs stub)
// name prop works
it('saves to localStorage with name', () => {
cy.mount(<Checkbox name="test" />)
cy.get('span').click()
expect(localStorage.getItem('test')).to.eq('true')
})
// stats tracking works (needs stub)
})

View File

@@ -1,61 +1,51 @@
import variables from 'config/variables';
import { PureComponent } from 'react';
import { Checkbox as CheckboxUI, FormControlLabel } from '@mui/material';
import { useEffect, useState } from 'react';
import { Checkbox as CheckboxUI, Field, Label } from '@headlessui/react';
import { MdCheckBox } from 'react-icons/md';
import EventBus from 'utils/eventbus';
class Checkbox extends PureComponent {
constructor(props) {
super(props);
this.state = {
checked: localStorage.getItem(this.props.name) === 'true',
};
}
const Checkbox = (props) => {
const [checked, setChecked] = useState(localStorage.getItem(props.name) === 'true');
handleChange = () => {
const value = this.state.checked !== true;
localStorage.setItem(this.props.name, value);
useEffect(() => {
setChecked(localStorage.getItem(props.name) === 'true');
}, [props.name]);
this.setState({
checked: value,
});
const handleChange = () => {
const value = !checked;
localStorage.setItem(props.name, value.toString());
if (this.props.onChange) {
this.props.onChange(value);
setChecked(value);
if (props.onChange) {
props.onChange(value);
}
variables.stats.postEvent(
'setting',
`${this.props.name} ${this.state.checked === true ? 'enabled' : 'disabled'}`,
);
variables.stats.postEvent('setting', props.name, value ? 'enabled' : 'disabled');
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
if (props.element) {
if (!document.querySelector(props.element)) {
document.querySelector('.reminder-info').style.display = 'flex';
return localStorage.setItem('showReminder', true);
localStorage.setItem('showReminder', 'true');
}
}
EventBus.emit('refresh', this.props.category);
EventBus.emit('refresh', props.category);
};
render() {
return (
<FormControlLabel
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}
/>
);
}
}
return (
<Field className="w-[300px] h-9 my-1 flex flex-row-reverse items-center gap-2 justify-between text-left">
<CheckboxUI
checked={checked}
onChange={handleChange}
disabled={props.disabled || false}
className="border border-[#484848] bg-white/5 group size-4 rounded-sm data-[checked]:bg-neutral-900 cursor-pointer grid place-content-center"
>
<MdCheckBox className="stroke-white opacity-0 group-data-[checked]:opacity-100 size-6" />
</CheckboxUI>
<Label>{props.text}</Label>
</Field>
);
};
export { Checkbox as default, Checkbox };

View File

@@ -1,78 +1,86 @@
import variables from 'config/variables';
import { PureComponent, createRef } from 'react';
import { InputLabel, MenuItem, FormControl, Select } from '@mui/material';
import { useState } from 'react';
import { Field, Label, Select } from '@headlessui/react';
import clsx from 'clsx';
import EventBus from 'utils/eventbus';
import variables from 'config/variables';
class Dropdown extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || this.props.items[0].value,
title: '',
};
this.dropdown = createRef();
}
const Dropdown = (props) => {
const [value, setValue] = useState(localStorage.getItem(props.name) || props.items[0]?.value);
onChange = (e) => {
const { value } = e.target;
if (value === variables.getMessage('modals.main.loading')) {
const handleChange = (e) => {
const newValue = e.target.value;
if (newValue === variables.getMessage('modals.main.loading')) {
return;
}
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
setValue(newValue);
this.setState({
value,
});
if (!this.props.noSetting) {
localStorage.setItem(this.props.name, value);
localStorage.setItem(this.props.name2, this.props.value2);
if (!props.noSetting) {
localStorage.setItem(props.name, newValue);
localStorage.setItem(props.name2, props.value2);
}
if (this.props.onChange) {
this.props.onChange(value);
if (props.onChange) {
props.onChange(newValue);
}
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
if (props.element) {
if (!document.querySelector(props.element)) {
document.querySelector('.reminder-info').style.display = 'flex';
return localStorage.setItem('showReminder', true);
}
}
EventBus.emit('refresh', this.props.category);
EventBus.emit('refresh', props.category);
};
render() {
const id = 'dropdown' + this.props.name;
const label = this.props.label || '';
const selectedItem = props.items.find((item) => item?.value === value);
return (
<FormControl fullWidth className={id}>
<InputLabel id={id}>{label}</InputLabel>
return (
<Field className="w-[100%] max-w-md mr-10">
{props.label && <Label className="mb-2 block text-sm font-medium">{props.label}</Label>}
<div className="relative">
<Select
labelId={id}
id={this.props.name}
value={this.state.value}
label={label}
onChange={this.onChange}
ref={this.dropdown}
key={id}
name={props.name}
value={value}
onChange={handleChange}
aria-label={props.label || props.name}
className={clsx(
'w-full rounded-lg py-4 px-5 text-sm/6 font-semibold text-white shadow-md',
'bg-white/5 hover:bg-white/10 dark:text-white',
'border border-white/10',
'transition-colors duration-200',
'focus:outline-none data-[focus]:outline-1 data-[focus]:outline-white',
'data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed',
'appearance-none',
)}
style={{
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='2' stroke='white' class='w-6 h-6'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19.5 8.25l-7.5 7.5-7.5-7.5' /%3E%3C/svg%3E")`,
backgroundRepeat: 'no-repeat',
backgroundPosition: 'right 1.25rem center',
backgroundSize: '1rem',
}}
>
{this.props.items.map((item) =>
{props.items.map((item) =>
item !== null ? (
<MenuItem key={id + item.value} value={item.value}>
<option
key={item.value}
value={item.value}
className="bg-modal-content-light dark:bg-modal-content-dark"
>
{item.text}
</MenuItem>
</option>
) : null,
)}
</Select>
</FormControl>
);
}
}
</div>
{selectedItem?.description && (
<p className="mt-2 text-sm text-white/50">{selectedItem.description}</p>
)}
</Field>
);
};
export { Dropdown as default, Dropdown };

View File

@@ -1,65 +1,53 @@
import variables from 'config/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { compressAccurately, filetoDataURL } from 'image-conversion';
import videoCheck from 'features/background/api/videoCheck';
class FileUpload extends PureComponent {
componentDidMount() {
document.getElementById(this.props.id).onchange = (e) => {
const reader = new FileReader();
const file = e.target.files[0];
function FileUpload({ id, type, accept, loadFunction }) {
const handleChange = (e) => {
const reader = new FileReader();
const file = e.target.files[0];
if (this.props.type === 'settings') {
reader.readAsText(file, 'UTF-8');
reader.onload = (e) => {
return this.props.loadFunction(e.target.result);
};
} else {
// background upload
const settings = {};
if (type === 'settings') {
reader.readAsText(file, 'UTF-8');
reader.onload = (e) => {
return loadFunction(e.target.result);
};
} else {
// background upload
const settings = {};
Object.keys(localStorage).forEach((key) => {
settings[key] = localStorage.getItem(key);
});
Object.keys(localStorage).forEach((key) => {
settings[key] = localStorage.getItem(key);
});
const settingsSize = new TextEncoder().encode(JSON.stringify(settings)).length;
if (videoCheck(file.type) === true) {
if (settingsSize + file.size > 4850000) {
return toast(variables.getMessage('toasts.no_storage'));
}
return this.props.loadFunction(file);
const settingsSize = new TextEncoder().encode(JSON.stringify(settings)).length;
if (videoCheck(file.type) === true) {
if (settingsSize + file.size > 4850000) {
return toast(variables.getMessage('toasts.no_storage'));
}
compressAccurately(file, {
size: 450,
accuracy: 0.9,
}).then(async (res) => {
if (settingsSize + res.size > 4850000) {
return toast(variables.getMessage('toasts.no_storage'));
}
this.props.loadFunction({
target: {
result: await filetoDataURL(res),
},
});
});
return loadFunction(file);
}
};
}
render() {
return (
<input
id={this.props.id}
type="file"
style={{ display: 'none' }}
accept={this.props.accept}
/>
);
}
loadFunction(
{
target: {
result: file,
},
},
);
}
};
return (
<input
id={id}
type="file"
style={{ display: 'none' }}
accept={accept}
onChange={handleChange}
/>
);
}
export { FileUpload as default, FileUpload };

View File

@@ -1,87 +1,82 @@
import variables from 'config/variables';
import { PureComponent } from 'react';
import {
Radio as RadioUI,
RadioGroup,
FormControlLabel,
FormControl,
FormLabel,
} from '@mui/material';
import { useState } from 'react';
import { Radio as PureRadio, RadioGroup } from '@headlessui/react';
import { MdCheckCircle } from 'react-icons/md';
import EventBus from 'utils/eventbus';
import { translations } from 'lib/translations';
class Radio extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name),
};
}
handleChange = async (e) => {
const { value } = e.target;
function Radio(props) {
const [value, setValue] = useState(localStorage.getItem(props.name));
const handleChange = async (value) => {
if (value === 'loading') {
return;
}
if (this.props.name === 'language') {
if (props.name === 'language') {
// old tab name
if (localStorage.getItem('tabName') === variables.getMessage('tabname')) {
localStorage.setItem('tabName', translations[value.replace('-', '_')].tabname);
}
// TODO: was this important?
// if (localStorage.getItem('tabName') === variables.getMessage('tabname')) {
// localStorage.setItem('tabName', translations[value].tabname);
// }
}
localStorage.setItem(this.props.name, value);
localStorage.setItem(props.name, value);
this.setState({
value,
});
setValue(value);
if (this.props.onChange) {
this.props.onChange(value);
if (props.onChange) {
props.onChange(value);
}
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
if (props.name !== 'language') {
variables.stats.postEvent('setting', props.name, `${value}-${value}`);
} else {
variables.stats.postEvent('language', props.name, `${value}-${value}`);
}
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
if (props.element) {
if (!document.querySelector(props.element)) {
document.querySelector('.reminder-info').style.display = 'flex';
return localStorage.setItem('showReminder', true);
}
}
EventBus.emit('refresh', this.props.category);
EventBus.emit('refresh', props.category);
};
render() {
return (
<FormControl component="fieldset">
<FormLabel
className={this.props.smallTitle ? 'radio-title-small' : 'radio-title'}
component="legend"
>
{this.props.title}
</FormLabel>
<RadioGroup
aria-label={this.props.name}
name={this.props.name}
onChange={this.handleChange}
value={this.state.value}
>
{this.props.options.map((option) => (
<FormControlLabel
value={option.value}
control={<RadioUI />}
label={option.name}
key={option.name}
/>
))}
</RadioGroup>
</FormControl>
);
}
return (
<div className="w-full">
<RadioGroup
aria-label={props.name}
name={props.name}
onChange={handleChange}
value={value}
className="space-y-2"
>
{props.options.map((option) => (
<PureRadio
key={option.name}
label={option.name}
value={option.value}
className="data-[checked]:bg-white/10 group relative flex cursor-pointer rounded-lg bg-white/5 dark:data-[checked]:hover:bg-neutral-700 dark:hover:bg-neutral-700 dark:data-[checked]:hover:bg-neutral-700 hover:bg-neutral-200 py-4 px-5 dark:text-white text-black shadow-md transition focus:outline-none data-[focus]:outline-1 data-[focus]:outline-white"
>
<div className="flex w-full items-center justify-between">
<div className="text-sm/6">
<p className="font-semibold capitalize">{option.name}</p>
<div className="flex gap-2 dark:text-white/50">
<div>{option.subname}</div>
<div aria-hidden="true">&middot;</div>
<div>10%</div>
</div>
</div>
<MdCheckCircle className="size-6 dark:fill-white fill-black opacity-0 transition group-data-[checked]:opacity-100" />
</div>
</PureRadio>
))}
</RadioGroup>
</div>
);
}
export { Radio as default, Radio };

View File

@@ -1,88 +1,361 @@
import variables from 'config/variables';
import { PureComponent } from 'react';
import { useState, useCallback, memo, useMemo, useRef } from 'react';
import { toast } from 'react-toastify';
import { Slider } from '@mui/material';
import { MdRefresh } from 'react-icons/md';
import ReactSlider from 'react-slider';
import { MdRefresh, MdEdit } from 'react-icons/md';
import EventBus from 'utils/eventbus';
import clsx from 'clsx';
import debounce from 'lodash/debounce';
class SliderComponent extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || this.props.default,
};
}
// Style definitions split into logical groups for better readability
const buttonStyles = {
base: 'inline-flex items-center text-sm px-3 py-1.5 rounded-md font-medium',
colors: 'bg-neutral-200 hover:bg-neutral-300 active:bg-neutral-400',
darkMode: 'dark:bg-white/10 dark:hover:bg-white/15 dark:active:bg-white/20',
text: 'text-neutral-800 dark:text-white',
transitions: 'transition-colors duration-200',
};
handleChange = (e, text) => {
let { value } = e.target;
value = Number(value);
const thumbStyles = {
base: [
'w-5 h-5 rounded-full cursor-pointer',
'absolute top-1/2',
'flex items-center justify-center',
'-translate-y-1/2', // Keep only Y transform in classes
],
colors: 'bg-gradient-to-br from-neutral-50 to-neutral-200 dark:from-white dark:to-neutral-100',
interactions: [
'hover:from-neutral-100 hover:to-neutral-300',
'dark:hover:from-white dark:hover:to-neutral-200',
'focus:outline-none focus:ring-2 focus:ring-neutral-400 dark:focus:ring-white/40',
],
// Remove transition-all which was causing lag
effects: 'shadow-lg shadow-black/10 dark:shadow-black/25',
tooltip: [
'before:content-[attr(aria-valuenow)]',
'before:absolute before:top-[-28px]',
'before:text-xs before:bg-neutral-800 dark:before:bg-black/90',
'before:text-white before:px-2 before:py-1 before:rounded-md',
'before:opacity-0 hover:before:opacity-100',
'before:transition-all before:duration-200 before:whitespace-nowrap',
'before:shadow-lg',
],
};
if (text) {
if (value === '') {
return this.setState({
value: 0,
});
}
const markStyles = {
base: [
'h-3 w-1.5 rounded-full cursor-pointer select-none',
'absolute top-1/2 transform -translate-y-1/2',
],
colors: 'bg-neutral-400 dark:bg-white/30',
hover: 'hover:bg-neutral-600 dark:hover:bg-white/50 hover:scale-110',
transitions: 'hover:transition-transform hover:duration-200',
label: [
'after:content-[attr(data-value)]',
'after:absolute after:top-5',
'after:text-xs after:opacity-85',
'after:left-1/2', // Add this to position relative to center
'after:transform after:-translate-x-1/2', // Center the label
'after:whitespace-nowrap after:pointer-events-none',
'after:font-medium',
'after:text-center', // Ensure text is centered
'after:text-neutral-700 dark:after:text-white/85',
],
};
if (value > this.props.max) {
value = this.props.max;
}
const MULTIPLIER_MARKS = {
10: '0.1x',
100: '1x',
200: '2x',
400: '4x',
};
if (value < this.props.min) {
value = this.props.min;
}
}
// Update ValueDisplay component to show edit affordance
const ValueDisplay = memo(({ value, display, onChange, min, max }) => {
const [editing, setEditing] = useState(false);
const [inputValue, setInputValue] = useState(value);
localStorage.setItem(this.props.name, value);
this.setState({
value,
});
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
document.querySelector('.reminder-info').style.display = 'flex';
return localStorage.setItem('showReminder', true);
}
}
EventBus.emit('refresh', this.props.category);
const handleChange = (e) => {
// Allow typing any numeric input, validate on blur
const numericValue = e.target.value.replace(/[^\d.-]/g, '');
setInputValue(numericValue);
};
resetItem = () => {
this.handleChange({
target: {
value: this.props.default || '',
},
});
const handleBlur = () => {
setEditing(false);
const numValue = Number(inputValue);
// Only validate and clamp on blur
if (!isNaN(numValue)) {
const clampedValue = Math.min(Math.max(numValue, min), max);
setInputValue(clampedValue);
onChange(clampedValue);
} else {
setInputValue(value);
}
};
const handleKeyDown = (e) => {
if (e.key === 'Enter') {
handleBlur();
} else if (e.key === 'Escape') {
setEditing(false);
setInputValue(value);
}
};
return editing ? (
<input
type="number" // Change to number type
value={inputValue}
onChange={handleChange}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
min={min} // Optional: add min/max if needed
max={max}
step="any" // Allow decimal values
className="w-20 text-sm bg-neutral-200 dark:bg-white/15 text-neutral-800 dark:text-white
px-3 py-1.5 rounded-md font-medium outline-none focus:ring-2
focus:ring-neutral-400 dark:focus:ring-white/40
[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none
transition-colors duration-200" // Added transition
autoFocus
/>
) : (
<div
onClick={() => setEditing(true)}
className="group relative flex items-center gap-2 text-sm bg-neutral-200 dark:bg-white/15
text-neutral-800 dark:text-white px-3 py-1.5 rounded-md font-medium cursor-pointer
hover:bg-neutral-300 dark:hover:bg-white/20 transition-colors duration-200"
>
<span className="flex items-center">
{value}
<span className="text-neutral-500 dark:text-white/50 ml-0.5">{display}</span>
</span>
<MdEdit className="w-4 h-4 opacity-50 group-hover:opacity-100 transition-opacity" />
<span
className="absolute -top-8 left-1/2 -translate-x-1/2 px-2 py-1 bg-neutral-800
dark:bg-black/90 text-white text-xs rounded opacity-0 group-hover:opacity-100
transition-opacity duration-200 whitespace-nowrap"
>
Click to edit
</span>
</div>
);
});
// Memoized reset button component
const ResetButton = memo(({ onClick }) => (
<button
onClick={onClick}
className={clsx(
buttonStyles.base,
buttonStyles.colors,
buttonStyles.darkMode,
buttonStyles.text,
buttonStyles.transitions,
)}
>
<MdRefresh className="w-4 h-4 mr-1.5" />
{variables.getMessage('settings:buttons.reset')}
</button>
));
function SliderComponent(props) {
const [value, setValue] = useState(() => {
try {
const stored = localStorage.getItem(props.name);
return stored ? Number(stored) : Number(props.default);
} catch (e) {
return Number(props.default);
}
});
const isDraggingRef = useRef(false);
const lastUpdateRef = useRef(value);
// Separated storage update from visual update
const updateStorage = useCallback(
(newValue) => {
try {
localStorage.setItem(props.name, newValue);
lastUpdateRef.current = newValue;
if (props.element && !document.querySelector(props.element)) {
const reminderElement = document.querySelector('.reminder-info');
if (reminderElement) {
reminderElement.style.display = 'flex';
localStorage.setItem('showReminder', true);
return;
}
}
EventBus.emit('refresh', props.category);
} catch (e) {
console.error('Error updating slider:', e);
}
},
[props.element, props.category],
);
// More efficient debounced storage update
const debouncedUpdate = useMemo(() => debounce(updateStorage, 150), [updateStorage]);
const handleChange = useCallback(
(newValue) => {
if (typeof newValue !== 'number') return;
const clampedValue = Math.min(Math.max(newValue, props.min), props.max);
// Always update visual state immediately
setValue(clampedValue);
// Only update storage if we're not actively dragging
if (!isDraggingRef.current) {
debouncedUpdate(clampedValue);
}
},
[props.min, props.max, debouncedUpdate],
);
const handleDragStart = useCallback(() => {
isDraggingRef.current = true;
}, []);
const handleDragEnd = useCallback(() => {
isDraggingRef.current = false;
// Ensure final value is stored
if (lastUpdateRef.current !== value) {
updateStorage(value);
}
}, [value, updateStorage]);
// Update thumbStyles to include performance optimizations
const enhancedThumbStyles = {
...thumbStyles,
performance: [
'will-change-transform',
'transform translate3d(0,0,0)',
'backface-visibility-hidden',
],
};
const resetItem = useCallback(() => {
handleChange(Number(props.default));
toast(variables.getMessage('toasts.reset'));
};
}, [props.default, handleChange]);
render() {
return (
<>
<span className={'sliderTitle'}>
{this.props.title}
<span>{Number(this.state.value)}</span>
<span className="link" onClick={this.resetItem}>
<MdRefresh />
{variables.getMessage('modals.main.settings.buttons.reset')}
</span>
</span>
<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 || []}
const handleMarkClick = useCallback(
(markValue) => {
handleChange(markValue);
},
[handleChange],
);
// Memoized render functions to prevent unnecessary re-renders
const renderThumb = useMemo(
() => (thumbProps, state) => (
<div
{...thumbProps}
style={{
...thumbProps.style,
left: thumbProps.style.left,
marginLeft: 0,
transform: 'translateY(-50%)', // Only handle Y transform here
}}
aria-label={`Slider value: ${state.valueNow}%`}
aria-valuenow={`${state.valueNow}${props.display}`}
role="slider"
aria-valuemin={state.valueMin}
aria-valuemax={state.valueMax}
/>
),
[props.display],
);
const renderMark = useMemo(
() => (markProps) => {
if (!MULTIPLIER_MARKS[markProps.key]) return null;
return (
<div
{...markProps}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleMarkClick(markProps.key);
}}
onMouseDown={(e) => e.preventDefault()}
data-value={MULTIPLIER_MARKS[markProps.key]}
role="button"
tabIndex={0}
aria-label={`Set zoom to ${MULTIPLIER_MARKS[markProps.key]}`}
className={`${markProps.className} cursor-pointer`}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleMarkClick(markProps.key);
}
}}
/>
</>
);
}
);
},
[handleMarkClick],
);
return (
<div className="w-full">
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium text-neutral-800 dark:text-white">{props.title}</span>
<div className="flex items-center gap-2 justify-between w-full">
<ValueDisplay
value={value}
display={props.display}
onChange={handleChange}
min={Number(props.min)}
max={Number(props.max)}
/>
<ResetButton onClick={resetItem} />
</div>
</div>
<ReactSlider
value={value}
onChange={handleChange}
onBeforeChange={handleDragStart}
onAfterChange={handleDragEnd}
min={Number(props.min)}
max={Number(props.max)}
step={Number(props.step) || 1}
marks={Object.keys(MULTIPLIER_MARKS).map(Number)}
snapPoints={Object.keys(MULTIPLIER_MARKS).map(Number)}
snap
className="h-14 flex items-center touch-none"
thumbClassName={clsx([
...thumbStyles.base,
thumbStyles.colors,
...thumbStyles.interactions,
thumbStyles.effects,
...thumbStyles.tooltip,
'touch-none',
'left-0', // Add this to ensure proper positioning
])}
trackClassName="h-2 bg-neutral-300 dark:bg-white/15 rounded-full absolute top-1/2 transform -translate-y-1/2 touch-none"
markClassName={clsx([
...markStyles.base,
markStyles.colors,
markStyles.hover,
markStyles.transitions,
...markStyles.label,
])}
renderThumb={renderThumb}
renderMark={renderMark}
/>
</div>
);
}
export { SliderComponent as default, SliderComponent as Slider };
// Export memoized version for better performance when parent components re-render
const Slider = memo(SliderComponent);
Slider.displayName = 'Slider';
export { Slider as default, Slider };

View File

@@ -1,60 +1,53 @@
import variables from 'config/variables';
import { PureComponent } from 'react';
import { Switch as SwitchUI, FormControlLabel } from '@mui/material';
import { useState } from 'react';
import { Field, Label, Switch as SwitchUI } from '@headlessui/react';
import EventBus from 'utils/eventbus';
class Switch extends PureComponent {
constructor(props) {
super(props);
this.state = {
checked: localStorage.getItem(this.props.name) === 'true',
};
}
function Switch(props) {
const [checked, setChecked] = useState(localStorage.getItem(props.name) === 'true');
handleChange = () => {
const value = this.state.checked !== true;
localStorage.setItem(this.props.name, value);
const handleChange = () => {
const value = checked !== true;
localStorage.setItem(props.name, value);
this.setState({
checked: value,
});
setChecked(value);
if (this.props.onChange) {
this.props.onChange(value);
if (props.onChange) {
props.onChange(value);
}
variables.stats.postEvent(
'setting',
`${this.props.name} ${this.state.checked === true ? 'enabled' : 'disabled'}`,
`${props.name} ${checked === true ? 'enabled' : 'disabled'}`,
);
if (this.props.element) {
if (!document.querySelector(this.props.element)) {
if (props.element) {
if (!document.querySelector(props.element)) {
document.querySelector('.reminder-info').style.display = 'flex';
return localStorage.setItem('showReminder', true);
}
}
EventBus.emit('refresh', this.props.category);
EventBus.emit('refresh', props.category);
};
render() {
return (
<FormControlLabel
control={
<SwitchUI
name={this.props.name}
color="primary"
checked={this.state.checked}
onChange={this.handleChange}
/>
}
label={this.props.header ? '' : this.props.text}
labelPlacement="start"
/>
);
}
return (
<Field className="flex flex-row items-center justify-between w-[100%]">
<Label>{props.header ? '' : props.text}</Label>
<SwitchUI
checked={checked}
onChange={handleChange}
className="box-border group relative flex h-7 w-14 cursor-pointer rounded-full bg-white/10 p-1 transition-colors duration-200 ease-in-out focus:outline-none data-[focus]:outline-1 data-[focus]:outline-white data-[checked]:bg-white/10"
>
{' '}
<span
aria-hidden="true"
className="pointer-events-none inline-block size-5 translate-x-0 rounded-full bg-white ring-0 shadow-lg transition duration-200 ease-in-out group-data-[checked]:translate-x-7"
/>
</SwitchUI>
</Field>
);
}
export { Switch as default, Switch };

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