Compare commits

..

26 Commits

Author SHA1 Message Date
Sabe Jones 79f83d87d0 4.143.1 2020-05-29 10:33:55 -05:00
Sabe Jones c9bf157c23 fix(achievements): show-all layout 2020-05-29 10:33:30 -05:00
Sabe Jones e54425f947 4.143.0 2020-05-28 16:51:43 -05:00
Sabe Jones d953ea14da Merge branch 'develop' into release 2020-05-28 16:51:37 -05:00
Sabe Jones 0c179fee2f chore(sprites): compile 2020-05-28 16:51:20 -05:00
Sabe Jones 05e229ccb0 feat(content): subscriber items June 2020 2020-05-28 16:51:12 -05:00
Alys b29d937806 replace Trello link with Google form link in GitHub CONTRIBUTING page 2020-05-28 15:42:32 +10:00
Matteo Pagliazzi 670b6a1563 fix(ui): adjust loading gryphon sizes and search members dropdown 2020-05-26 18:02:48 +02:00
Matteo Pagliazzi 08f1e2b273 Client: remove unnecessary API calls + members fixes (#12179)
* wip

* refactor world state

* allow resource to be reloaded when the server is updated

* fix #9242

* fix event listeners

* remove un-needed code

* add tests for  asyncResourceFactory reloadOnAppVersionChange

* fix double cron notifications and party members showing up in the header after a party invitation is accepted

* remove console.log

* do not send vm info to loggly due to circular dependency + fix typo

* fix #12181

* do not load invites multiple times in members modal

* add hover to challenge member count

* groups: load members only on demand

* minor ui fixes

* choose class: fix vue duplicate key warning

* minor ui fixes

* challanges: load members on demand

* add loading spinner

* change loading mechanism

* fix loading gryphon issues

* reduce code duplication
2020-05-25 17:02:29 +02:00
dependabot-preview[bot] ca80f4ee33 build(deps): bump @storybook/addon-knobs in /website/client (#12243)
Bumps [@storybook/addon-knobs](https://github.com/storybookjs/storybook/tree/HEAD/addons/knobs) from 5.3.18 to 5.3.19.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v5.3.19/addons/knobs)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 13:11:34 +02:00
dependabot-preview[bot] 65cbee9e75 build(deps): bump @storybook/addon-notes in /website/client (#12245)
Bumps [@storybook/addon-notes](https://github.com/storybookjs/storybook/tree/HEAD/addons/notes) from 5.3.18 to 5.3.19.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v5.3.19/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v5.3.19/addons/notes)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-05-25 13:05:02 +02:00
dependabot-preview[bot] 0f8563c14e build(deps): bump inspectpack from 4.4.0 to 4.5.2 in /website/client (#12246)
Bumps [inspectpack](https://github.com/FormidableLabs/inspectpack) from 4.4.0 to 4.5.2.
- [Release notes](https://github.com/FormidableLabs/inspectpack/releases)
- [Changelog](https://github.com/FormidableLabs/inspectpack/blob/master/HISTORY.md)
- [Commits](https://github.com/FormidableLabs/inspectpack/compare/v4.4.0...v4.5.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:55:35 +02:00
dependabot-preview[bot] c4117f99ed build(deps): bump @storybook/addon-actions in /website/client (#12242)
Bumps [@storybook/addon-actions](https://github.com/storybookjs/storybook/tree/HEAD/addons/actions) from 5.3.18 to 5.3.19.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v5.3.19/addons/actions)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:55:19 +02:00
dependabot-preview[bot] 27aca19c8c build(deps): bump @storybook/vue in /website/client (#12238)
Bumps [@storybook/vue](https://github.com/storybookjs/storybook/tree/HEAD/app/vue) from 5.3.18 to 5.3.19.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v5.3.19/app/vue)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:55:07 +02:00
dependabot-preview[bot] 80c18ffadd build(deps): bump bootstrap-vue from 2.14.0 to 2.15.0 in /website/client (#12239)
Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.14.0 to 2.15.0.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.14.0...v2.15.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:54:56 +02:00
dependabot-preview[bot] bf2c4eb501 build(deps): bump moment from 2.25.3 to 2.26.0 in /website/client (#12244)
Bumps [moment](https://github.com/moment/moment) from 2.25.3 to 2.26.0.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.25.3...2.26.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:54:20 +02:00
dependabot-preview[bot] ab1828c914 build(deps): bump vue-router from 3.1.6 to 3.2.0 in /website/client (#12237)
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.1.6 to 3.2.0.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.1.6...v3.2.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:54:03 +02:00
dependabot-preview[bot] b32f79f682 build(deps): bump @storybook/addon-links in /website/client (#12236)
Bumps [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/addons/links) from 5.3.18 to 5.3.19.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v5.3.19/addons/links)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:53:39 +02:00
dependabot-preview[bot] 7b69289069 build(deps): bump moment from 2.25.3 to 2.26.0 (#12231)
Bumps [moment](https://github.com/moment/moment) from 2.25.3 to 2.26.0.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.25.3...2.26.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:53:25 +02:00
dependabot-preview[bot] a1fb80868f build(deps): bump mongoose from 5.9.14 to 5.9.15 (#12230)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.9.14 to 5.9.15.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.9.14...5.9.15)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 12:04:49 +02:00
Carl Vuorinen 9d4fb80d15 Add close button to profile modal (#12203) 2020-05-22 17:48:15 +02:00
Matteo Pagliazzi 43392f4952 Merge branch 'release' into develop 2020-05-22 17:46:14 +02:00
dependabot-preview[bot] 6e46794822 build(deps): bump bootstrap from 4.4.1 to 4.5.0 in /website/client (#12211)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 4.4.1 to 4.5.0.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v4.4.1...v4.5.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-22 17:45:25 +02:00
Matteo Pagliazzi 032c95d5c8 fix(avatar transormation): move questProgress method to spells mixin so that it is always available 2020-05-22 13:28:44 +02:00
Melior b40411e219 Merge branch 'origin/develop' into Weblate. 2020-05-21 22:02:19 +02:00
Melior 86410f6bb7 Translated using Weblate (Russian)
Currently translated at 90.3% (75 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/

Translated using Weblate (Russian)

Currently translated at 87.9% (73 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/

Translated using Weblate (French)

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/

Translated using Weblate (German)

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/

Translated using Weblate (Polish)

Currently translated at 100.0% (248 of 248 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pl/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (248 of 248 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/bg/

Translated using Weblate (Polish)

Currently translated at 100.0% (140 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (172 of 172 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (492 of 492 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pl/

Translated using Weblate (Portuguese)

Currently translated at 82.9% (1745 of 2103 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt/

Translated using Weblate (Dutch)

Currently translated at 93.7% (1965 of 2095 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Polish)

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pl/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/bg/

Translated using Weblate (French)

Currently translated at 100.0% (696 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (Polish)

Currently translated at 100.0% (358 of 358 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/pl/

Translated using Weblate (Polish)

Currently translated at 91.5% (76 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (211 of 211 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pl/

Translated using Weblate (Polish)

Currently translated at 80.7% (67 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 80.7% (67 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Japanese)

Currently translated at 87.8% (159 of 181 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (358 of 358 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ja/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/

Translated using Weblate (English)

Currently translated at 0.9% (3 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/en@lolcat/

Translated using Weblate (Bulgarian)

Currently translated at 91.3% (483 of 529 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/bg/

Translated using Weblate (English (Pirate))

Currently translated at 87.9% (73 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 87.9% (73 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/

Translated using Weblate (Polish)

Currently translated at 99.5% (210 of 211 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pl/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (211 of 211 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/bg/

Translated using Weblate (Bulgarian)

Currently translated at 99.5% (247 of 248 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/bg/

Translated using Weblate (Bulgarian)

Currently translated at 99.5% (247 of 248 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/bg/

Translated using Weblate (Polish)

Currently translated at 100.0% (57 of 57 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/pl/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (140 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/pt_BR/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (140 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (143 of 143 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (172 of 172 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (492 of 492 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/bg/

Translated using Weblate (Bulgarian)

Currently translated at 99.6% (297 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/bg/

Translated using Weblate (Bulgarian)

Currently translated at 83.8% (1756 of 2095 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/bg/

Translated using Weblate (Polish)

Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (63 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (126 of 126 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pl/

Translated using Weblate (Bulgarian)

Currently translated at 85.2% (593 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/bg/

Translated using Weblate (Polish)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/pl/

Translated using Weblate (Bulgarian)

Currently translated at 90.9% (481 of 529 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/bg/

Translated using Weblate (Polish)

Currently translated at 78.3% (65 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (211 of 211 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/bg/

Translated using Weblate (Polish)

Currently translated at 53.0% (44 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 53.0% (44 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 50.6% (42 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 50.6% (42 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 48.1% (40 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 48.1% (40 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 44.5% (37 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 44.5% (37 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 43.3% (36 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 43.3% (36 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 42.1% (35 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 42.1% (35 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (28 of 28 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/bg/

Translated using Weblate (Polish)

Currently translated at 36.1% (30 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 36.1% (30 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 34.9% (29 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Polish)

Currently translated at 34.9% (29 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/bg/

Translated using Weblate (Bulgarian)

Currently translated at 99.3% (326 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (6 of 6 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/bg/

Translated using Weblate (Bulgarian)

Currently translated at 94.5% (465 of 492 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/bg/

Translated using Weblate (Bulgarian)

Currently translated at 83.7% (1755 of 2095 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (126 of 126 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/bg/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/bg/

Translated using Weblate (Bulgarian)

Currently translated at 98.7% (82 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/bg/

Translated using Weblate (Russian)

Currently translated at 99.1% (488 of 492 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ru/

Translated using Weblate (Dutch)

Currently translated at 93.6% (1963 of 2095 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (140 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 100.0% (143 of 143 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ja/

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (696 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hant/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (696 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en_GB/

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en_GB/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/es_419/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (696 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.7% (694 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (140 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (358 of 358 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.7% (82 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/

Translated using Weblate (German)

Currently translated at 100.0% (696 of 696 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (83 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/

Translated using Weblate (German)

Currently translated at 98.7% (82 of 83 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/
2020-05-21 22:02:08 +02:00
169 changed files with 8487 additions and 8196 deletions
+1
View File
@@ -10,6 +10,7 @@ dist/
dist-client/
apidoc_build/
content_cache/
i18n_cache/
node_modules/
# Old migrations, disabled
+1 -1
View File
@@ -8,7 +8,7 @@
# Requesting a feature
Habitica uses [Trello](https://trello.com/b/EpoYEYod/habitica) to track feature requests. [Read more](https://trello.com/c/odmhIqyW/440-read-first-table-of-contents).
Habitica uses [this Google form](https://docs.google.com/forms/d/e/1FAIpQLScPhrwq_7P1C6PTrI3lbvTsvqGyTNnGzp1ugi1Ml0PFee_p5g/viewform?usp=sf_link) to track feature requests. Please post there rather than creating an issue.
# Contributing Code
+7 -33
View File
@@ -1,6 +1,6 @@
{
"name": "habitica",
"version": "4.142.3",
"version": "4.143.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -9678,9 +9678,9 @@
"integrity": "sha1-EUyUlnPiqKNenTV4hSeqN7Z52is="
},
"moment": {
"version": "2.25.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz",
"integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg=="
"version": "2.26.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
"integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
},
"moment-recur": {
"version": "1.0.7",
@@ -9694,7 +9694,6 @@
"version": "3.5.7",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.7.tgz",
"integrity": "sha512-lMtleRT+vIgY/JhhTn1nyGwnSMmJkJELp+4ZbrjctrnBxuLbj6rmLuJFz8W2xUzUqWmqoyVxJLYuC58ZKpcTYQ==",
"dev": true,
"requires": {
"bl": "^2.2.0",
"bson": "^1.1.4",
@@ -9708,7 +9707,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz",
"integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==",
"dev": true,
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
@@ -9717,9 +9715,9 @@
}
},
"mongoose": {
"version": "5.9.14",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.14.tgz",
"integrity": "sha512-LScxCruQv0YpU/9DasKdThd+3r3PFQbCgesmfa6g0pTDOIiD1A9N9OQsGYrDf+dyUksfLCxJYYF9qpBHLvS1tg==",
"version": "5.9.15",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.15.tgz",
"integrity": "sha512-dGIDqaQkAJoLl7lsRLy70mDg+VcL1IPOHr/0f23MLF45PtnM5exRdmienfyVjdrSVGgTus+1sMUKef6vSnrDZg==",
"requires": {
"bson": "^1.1.4",
"kareem": "2.3.1",
@@ -9732,30 +9730,6 @@
"safe-buffer": "5.1.2",
"sift": "7.0.1",
"sliced": "1.0.1"
},
"dependencies": {
"bl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz",
"integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"mongodb": {
"version": "3.5.7",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.7.tgz",
"integrity": "sha512-lMtleRT+vIgY/JhhTn1nyGwnSMmJkJELp+4ZbrjctrnBxuLbj6rmLuJFz8W2xUzUqWmqoyVxJLYuC58ZKpcTYQ==",
"requires": {
"bl": "^2.2.0",
"bson": "^1.1.4",
"denque": "^1.4.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
}
}
},
"mongoose-legacy-pluralize": {
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.142.3",
"version": "4.143.1",
"main": "./website/server/index.js",
"dependencies": {
"@babel/core": "^7.9.6",
@@ -46,9 +46,9 @@
"lodash": "^4.17.15",
"merge-stream": "^2.0.0",
"method-override": "^3.0.0",
"moment": "^2.25.3",
"moment": "^2.26.0",
"moment-recur": "^1.0.7",
"mongoose": "^5.9.14",
"mongoose": "^5.9.15",
"morgan": "^1.10.0",
"nconf": "^0.10.0",
"node-gcm": "^1.0.2",
-16
View File
@@ -1,16 +0,0 @@
{
"env": {
"test": {
plugins: [
["istanbul"],
],
},
},
"presets": [
["es2015", { modules: false }],
],
"plugins": [
"transform-object-rest-spread",
],
"comments": false,
}
-21
View File
@@ -1,21 +0,0 @@
/* eslint-disable */
// TODO verify if it's needed, added because Axios require Promise in the global scope
// and babel-runtime doesn't affect external libraries
require('babel-polyfill');
// Automatically setup SinonJS' sandbox for each test
beforeEach(() => {
global.sandbox = sinon.createSandbox();
});
afterEach(() => {
global.sandbox.restore();
});
// require all test files
const testsContext = require.context('./specs', true, /\.js$/);
testsContext.keys().forEach(testsContext);
// require all .vue and .js files except main.js for coverage.
const srcContext = require.context('../../../website/client', true, /^\.\/(?=(?!main(\.js)?$))(?=(.*\.(vue|js)$))/);
srcContext.keys().forEach(srcContext);
-40
View File
@@ -1,40 +0,0 @@
/* eslint-disable */
// This is a karma config file. For more details see
// http://karma-runner.github.io/0.13/config/configuration-file.html
// we are also using it with karma-webpack
// https://github.com/webpack/karma-webpack
// Necessary for babel to respect the env version of .babelrc which is necessary
// Because inject-loader does not work with ["es2015", { modules: false }] that we use
// in order to let webpack2 handle the imports
process.env.CHROME_BIN = require('puppeteer').executablePath();
// eslint-disable-line no-process-env
process.env.BABEL_ENV = process.env.NODE_ENV; // eslint-disable-line no-process-env
const webpackConfig = require('../../../webpack/webpack.test.conf');
module.exports = function (config) {
config.set({
// to run in additional browsers:
// 1. install corresponding karma launcher
// http://karma-runner.github.io/0.13/config/browsers.html
// 2. add it to the `browsers` array below.
browsers: ['ChromeHeadless'],
frameworks: ['mocha', 'sinon-stub-promise', 'sinon-chai', 'chai-as-promised', 'chai'],
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap'],
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
},
coverageReporter: {
dir: '../../../coverage/client-unit',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' },
],
},
});
};
+843 -959
View File
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -13,11 +13,11 @@
"test:unit": "vue-cli-service test:unit --require ./tests/unit/helpers.js"
},
"dependencies": {
"@storybook/addon-actions": "^5.3.18",
"@storybook/addon-knobs": "^5.3.18",
"@storybook/addon-links": "^5.3.18",
"@storybook/addon-notes": "^5.3.18",
"@storybook/vue": "^5.3.18",
"@storybook/addon-actions": "^5.3.19",
"@storybook/addon-knobs": "^5.3.19",
"@storybook/addon-links": "^5.3.19",
"@storybook/addon-notes": "^5.3.19",
"@storybook/vue": "^5.3.19",
"@vue/cli-plugin-babel": "^4.3.1",
"@vue/cli-plugin-eslint": "^4.3.1",
"@vue/cli-plugin-router": "^4.3.1",
@@ -28,8 +28,8 @@
"axios": "^0.19.2",
"axios-progress-bar": "^1.2.0",
"babel-eslint": "^10.1.0",
"bootstrap": "^4.4.1",
"bootstrap-vue": "^2.14.0",
"bootstrap": "^4.5.0",
"bootstrap-vue": "^2.15.0",
"chai": "^4.1.2",
"core-js": "^3.6.5",
"eslint": "^6.8.0",
@@ -38,11 +38,11 @@
"eslint-plugin-vue": "^6.2.2",
"habitica-markdown": "^2.0.0",
"hellojs": "^1.18.4",
"inspectpack": "^4.4.0",
"inspectpack": "^4.5.2",
"intro.js": "^2.9.3",
"jquery": "^3.5.1",
"lodash": "^4.17.15",
"moment": "^2.25.3",
"moment": "^2.26.0",
"nconf": "^0.10.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
@@ -56,7 +56,7 @@
"vue": "^2.6.11",
"vue-cli-plugin-storybook": "^0.6.1",
"vue-mugen-scroll": "^0.2.6",
"vue-router": "^3.1.6",
"vue-router": "^3.2.0",
"vue-template-compiler": "^2.6.11",
"vuedraggable": "^2.23.2",
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",
+48 -51
View File
@@ -297,7 +297,7 @@ export default {
};
},
computed: {
...mapState(['isUserLoggedIn', 'browserTimezoneOffset', 'isUserLoaded']),
...mapState(['isUserLoggedIn', 'browserTimezoneOffset', 'isUserLoaded', 'notificationsRemoved']),
...mapState({ user: 'user.data' }),
isStaticPage () {
return this.$route.meta.requiresLogin === false;
@@ -361,13 +361,55 @@ export default {
showSpinner: false,
});
// Set up Error interceptors
axios.interceptors.response.use(response => {
if (this.user && response.data && response.data.notifications) {
this.$set(this.user, 'notifications', response.data.notifications);
axios.interceptors.response.use(response => { // Set up Response interceptors
// Verify that the user was not updated from another browser/app/client
// If it was, sync
const { url } = response.config;
const { method } = response.config;
const isApiCall = url.indexOf('api/v4') !== -1;
const userV = response.data && response.data.userV;
const isCron = url.indexOf('/api/v4/cron') === 0 && method === 'post';
if (this.isUserLoaded && isApiCall && userV) {
const oldUserV = this.user._v;
this.user._v = userV;
// Do not sync again if already syncing
const isUserSync = url.indexOf('/api/v4/user') === 0 && method === 'get';
const isTasksSync = url.indexOf('/api/v4/tasks/user') === 0 && method === 'get';
// exclude chat seen requests because with real time chat they would be too many
const isChatSeen = url.indexOf('/chat/seen') !== -1 && method === 'post';
// exclude POST /api/v4/cron because the user is synced automatically after cron runs
// Something has changed on the user object that was not tracked here, sync the user
if (userV - oldUserV > 1 && !isCron && !isChatSeen && !isUserSync && !isTasksSync) {
Promise.all([
this.$store.dispatch('user:fetch', { forceLoad: true }),
this.$store.dispatch('tasks:fetchUserTasks', { forceLoad: true }),
]);
}
}
// Store the app version from the server
const serverAppVersion = response.data && response.data.appVersion;
if (serverAppVersion && this.$store.state.serverAppVersion !== response.data.appVersion) {
this.$store.state.serverAppVersion = serverAppVersion;
}
// Store the notifications, filtering those that have already been read
// See store/index.js on why this is necessary
if (this.user && response.data && response.data.notifications) {
const filteredNotifications = response.data.notifications.filter(serverNotification => {
if (this.notificationsRemoved.includes(serverNotification.id)) return false;
return true;
});
this.$set(this.user, 'notifications', filteredNotifications);
}
return response;
}, error => {
}, error => { // Set up Error interceptors
if (error.response.status >= 400) {
const isBanned = this.checkForBannedUser(error);
if (isBanned === true) return null; // eslint-disable-line consistent-return
@@ -425,51 +467,6 @@ export default {
return Promise.reject(error);
});
axios.interceptors.response.use(response => {
// Verify that the user was not updated from another browser/app/client
// If it was, sync
const { url } = response.config;
const { method } = response.config;
const isApiCall = url.indexOf('api/v4') !== -1;
const userV = response.data && response.data.userV;
const isCron = url.indexOf('/api/v4/cron') === 0 && method === 'post';
if (this.isUserLoaded && isApiCall && userV) {
const oldUserV = this.user._v;
this.user._v = userV;
// Do not sync again if already syncing
const isUserSync = url.indexOf('/api/v4/user') === 0 && method === 'get';
const isTasksSync = url.indexOf('/api/v4/tasks/user') === 0 && method === 'get';
// exclude chat seen requests because with real time chat they would be too many
const isChatSeen = url.indexOf('/chat/seen') !== -1 && method === 'post';
// exclude POST /api/v4/cron because the user is synced automatically after cron runs
// Something has changed on the user object that was not tracked here, sync the user
if (userV - oldUserV > 1 && !isCron && !isChatSeen && !isUserSync && !isTasksSync) {
Promise.all([
this.$store.dispatch('user:fetch', { forceLoad: true }),
this.$store.dispatch('tasks:fetchUserTasks', { forceLoad: true }),
]);
}
}
// Verify the client is updated
// const serverAppVersion = response.data.appVersion;
// let serverAppVersionState = this.$store.state.serverAppVersion;
// if (isApiCall && !serverAppVersionState) {
// this.$store.state.serverAppVersion = serverAppVersion;
// } else if (isApiCall && serverAppVersionState !== serverAppVersion) {
// if (document.activeElement.tagName !== 'INPUT'
// || confirm(this.$t('habiticaHasUpdated'))) {
// location.reload(true);
// }
// }
return response;
});
// Setup listener for title
this.$store.watch(state => state.title, title => {
document.title = title;
@@ -22,9 +22,15 @@
width: 282px;
height: 147px;
}
.promo_mystery_202006 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -241px -582px;
width: 282px;
height: 147px;
}
.promo_take_this {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -391px -296px;
background-position: -815px -179px;
width: 96px;
height: 69px;
}
@@ -48,7 +54,7 @@
}
.scene_vikte {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -241px -582px;
background-position: -815px 0px;
width: 157px;
height: 178px;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -4,9 +4,15 @@
width: 221px;
height: 39px;
}
.quest_cow {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px 0px;
width: 174px;
height: 213px;
}
.quest_dilatory {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1320px -660px;
background-position: -440px -892px;
width: 219px;
height: 219px;
}
@@ -18,61 +24,61 @@
}
.quest_dilatoryDistress2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -1020px;
background-position: -1762px -875px;
width: 150px;
height: 150px;
}
.quest_dilatoryDistress3 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -220px -232px;
background-position: 0px -232px;
width: 219px;
height: 219px;
}
.quest_dilatory_derby {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -220px -672px;
background-position: -1320px 0px;
width: 219px;
height: 219px;
}
.quest_dolphin {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -440px -232px;
background-position: -220px -232px;
width: 219px;
height: 219px;
}
.quest_dustbunnies {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -660px 0px;
background-position: -440px -232px;
width: 219px;
height: 219px;
}
.quest_egg {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -359px;
background-position: -1762px -214px;
width: 165px;
height: 207px;
}
.quest_evilsanta {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -1171px;
background-position: -1762px -1026px;
width: 118px;
height: 131px;
}
.quest_evilsanta2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -220px -452px;
background-position: -660px -220px;
width: 219px;
height: 219px;
}
.quest_falcon {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -440px -452px;
background-position: 0px -452px;
width: 219px;
height: 219px;
}
.quest_ferret {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -660px -452px;
background-position: -220px -452px;
width: 219px;
height: 219px;
}
@@ -84,13 +90,13 @@
}
.quest_ghost_stag {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -880px -220px;
background-position: -660px -452px;
width: 219px;
height: 219px;
}
.quest_goldenknight1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -880px -440px;
background-position: -880px 0px;
width: 219px;
height: 219px;
}
@@ -108,19 +114,19 @@
}
.quest_gryphon {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -874px -1332px;
background-position: -1091px -1332px;
width: 216px;
height: 177px;
}
.quest_guineapig {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -660px -672px;
background-position: -220px -672px;
width: 219px;
height: 219px;
}
.quest_harpy {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -880px -672px;
background-position: -440px -672px;
width: 219px;
height: 219px;
}
@@ -132,109 +138,109 @@
}
.quest_hippo {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1100px -220px;
background-position: -880px -672px;
width: 219px;
height: 219px;
}
.quest_horse {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1100px -440px;
background-position: -1100px 0px;
width: 219px;
height: 219px;
}
.quest_kangaroo {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1100px -660px;
background-position: -220px 0px;
width: 219px;
height: 219px;
}
.quest_kraken {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1308px -1332px;
background-position: -874px -1332px;
width: 216px;
height: 177px;
}
.quest_lostMasterclasser1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -220px -892px;
background-position: -1100px -660px;
width: 219px;
height: 219px;
}
.quest_lostMasterclasser2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -440px -892px;
background-position: 0px -892px;
width: 219px;
height: 219px;
}
.quest_lostMasterclasser3 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -660px -892px;
background-position: -220px -892px;
width: 219px;
height: 219px;
}
.quest_mayhemMistiflying1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -869px;
background-position: -1762px -573px;
width: 150px;
height: 150px;
}
.quest_mayhemMistiflying2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1100px -892px;
background-position: -660px -892px;
width: 219px;
height: 219px;
}
.quest_mayhemMistiflying3 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1320px 0px;
background-position: -880px -892px;
width: 219px;
height: 219px;
}
.quest_monkey {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1320px -220px;
background-position: -1100px -892px;
width: 219px;
height: 219px;
}
.quest_moon1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1540px -648px;
background-position: -1540px -214px;
width: 216px;
height: 216px;
}
.quest_moon2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -220px 0px;
background-position: -1320px -220px;
width: 219px;
height: 219px;
}
.quest_moon3 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1320px -880px;
background-position: -1320px -440px;
width: 219px;
height: 219px;
}
.quest_moonstone1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: 0px -1112px;
background-position: -1320px -660px;
width: 219px;
height: 219px;
}
.quest_moonstone2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -220px -1112px;
background-position: -1320px -880px;
width: 219px;
height: 219px;
}
.quest_moonstone3 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -440px -1112px;
background-position: 0px -1112px;
width: 219px;
height: 219px;
}
.quest_nudibranch {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1540px -214px;
background-position: -1540px -1082px;
width: 216px;
height: 216px;
}
@@ -246,91 +252,91 @@
}
.quest_owl {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1100px -1112px;
background-position: -440px -1112px;
width: 219px;
height: 219px;
}
.quest_peacock {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1540px -1082px;
background-position: -1540px -648px;
width: 216px;
height: 216px;
}
.quest_penguin {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -175px;
background-position: 0px -1697px;
width: 190px;
height: 183px;
}
.quest_pterodactyl {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1320px -1112px;
background-position: -880px -1112px;
width: 219px;
height: 219px;
}
.quest_rat {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -880px -1112px;
background-position: -1100px -1112px;
width: 219px;
height: 219px;
}
.quest_robot {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -660px -1112px;
background-position: -440px -452px;
width: 219px;
height: 219px;
}
.quest_rock {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1540px -431px;
background-position: -1540px -865px;
width: 216px;
height: 216px;
}
.quest_rooster {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px 0px;
background-position: -1525px -1332px;
width: 213px;
height: 174px;
}
.quest_ruby {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1320px -440px;
background-position: -1320px -1112px;
width: 219px;
height: 219px;
}
.quest_sabretooth {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -880px -892px;
background-position: -220px -1112px;
width: 219px;
height: 219px;
}
.quest_seaserpent {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: 0px -892px;
background-position: -1100px -440px;
width: 219px;
height: 219px;
}
.quest_sheep {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1100px 0px;
background-position: -660px -672px;
width: 219px;
height: 219px;
}
.quest_silver {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -440px -672px;
background-position: 0px -672px;
width: 219px;
height: 219px;
}
.quest_slime {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: 0px -672px;
background-position: -880px -220px;
width: 219px;
height: 219px;
}
.quest_sloth {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -880px 0px;
background-position: -1100px -220px;
width: 219px;
height: 219px;
}
@@ -342,7 +348,7 @@
}
.quest_snake {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1091px -1332px;
background-position: -1308px -1332px;
width: 216px;
height: 177px;
}
@@ -354,37 +360,37 @@
}
.quest_squirrel {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: 0px -452px;
background-position: -660px -1112px;
width: 219px;
height: 219px;
}
.quest_stoikalmCalamity1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -567px;
background-position: -1762px -422px;
width: 150px;
height: 150px;
}
.quest_stoikalmCalamity2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -660px -220px;
background-position: -880px -440px;
width: 219px;
height: 219px;
}
.quest_stoikalmCalamity3 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: 0px -232px;
background-position: -660px 0px;
width: 219px;
height: 219px;
}
.quest_taskwoodsTerror1 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1762px -718px;
background-position: -1762px -724px;
width: 150px;
height: 150px;
}
.quest_taskwoodsTerror2 {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1540px -865px;
background-position: -1540px -431px;
width: 216px;
height: 216px;
}
@@ -394,9 +400,3 @@
width: 219px;
height: 219px;
}
.quest_treeling {
background-image: url('~@/assets/images/sprites/spritesmith-main-13.png');
background-position: -1525px -1332px;
width: 216px;
height: 177px;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 KiB

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 152 KiB

@@ -16,7 +16,7 @@
<div class="row">
<div
v-for="heroClass in classes"
:key="heroClass"
:key="`${heroClass}-avatar`"
class="col-md-3"
>
<div @click="selectedClass = heroClass">
@@ -60,7 +60,7 @@
</div>
<div
v-for="heroClass in classes"
:key="heroClass"
:key="`${heroClass}-explanation`"
>
<div
v-if="selectedClass === heroClass"
@@ -20,6 +20,7 @@
class="avatar"
:member="user"
:avatar-only="true"
:hide-class-badge="true"
:with-background="true"
/>
</div>
@@ -64,7 +64,7 @@ export default {
this.html = response.data.html;
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('bv::show::modal');
},
methods: {
@@ -55,7 +55,7 @@
</div>
<div class="col-12 col-md-6 text-right">
<div
class="box"
class="box member-count"
@click="showMemberModal()"
>
<div
@@ -93,6 +93,7 @@
:members="members"
:challenge-id="challengeId"
@member-selected="openMemberProgressModal"
@opened="initialMembersLoad()"
/>
</div>
<div class="col-12 col-md-6 text-right">
@@ -279,6 +280,10 @@
font-size: 20px;
vertical-align: bottom;
&.member-count:hover {
cursor: pointer;
}
.svg-icon {
width: 30px;
display: inline-block;
@@ -364,6 +369,7 @@ export default {
}),
challenge: {},
members: [],
membersLoaded: false,
tasksByType: {
habit: [],
daily: [],
@@ -427,8 +433,6 @@ export default {
this.$router.push('/challenges/findChallenges');
return;
}
this.members = await this
.loadMembers({ challengeId: this.searchId, includeAllPublicFields: true });
const tasks = await this.$store.dispatch('tasks:getChallengeTasks', { challengeId: this.searchId });
this.tasksByType = {
habit: [],
@@ -454,7 +458,22 @@ export default {
}
return this.$store.dispatch('members:getChallengeMembers', payload);
},
initialMembersLoad () {
this.$store.state.memberModalOptions.loading = true;
if (!this.membersLoaded) {
this.membersLoaded = true;
this.loadMembers({
challengeId: this.searchId,
includeAllPublicFields: true,
}).then(m => {
this.members.push(...m);
this.$store.state.memberModalOptions.loading = false;
});
} else {
this.$store.state.memberModalOptions.loading = false;
}
},
editTask (task) {
this.taskFormPurpose = 'edit';
this.editingTask = cloneDeep(task);
@@ -489,6 +508,8 @@ export default {
this.tasksByType[task.type].splice(index, 1);
},
showMemberModal () {
this.initialMembersLoad();
this.$root.$emit('habitica:show-member-modal', {
challengeId: this.challenge._id,
groupId: 'challenge', // @TODO: change these terrible settings
@@ -501,8 +522,8 @@ export default {
async joinChallenge () {
this.user.challenges.push(this.searchId);
this.challenge = await this.$store.dispatch('challenges:joinChallenge', { challengeId: this.searchId });
this.members = await this
.loadMembers({ challengeId: this.searchId, includeAllPublicFields: true });
this.membersLoaded = false;
this.members = [];
await this.$store.dispatch('tasks:fetchUserTasks', { forceLoad: true });
},
@@ -511,10 +532,11 @@ export default {
},
async updateChallenge () {
this.challenge = await this.$store.dispatch('challenges:getChallenge', { challengeId: this.searchId });
this.members = await this
.loadMembers({ challengeId: this.searchId, includeAllPublicFields: true });
this.membersLoaded = false;
this.members = [];
},
closeChallenge () {
this.initialMembersLoad();
this.$root.$emit('bv::show::modal', 'close-challenge-modal');
},
edit () {
@@ -223,7 +223,7 @@ export default {
created () {
window.addEventListener('scroll', this.handleScroll);
},
destroyed () {
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll);
},
methods: {
@@ -81,7 +81,7 @@ export default {
this.$root.$emit('bv::show::modal', 'copyAsTodo');
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica::copy-as-todo');
},
methods: {
@@ -122,10 +122,10 @@ export default {
};
},
},
created () {
mounted () {
this.$root.$on('habitica::report-chat', this.handleReport);
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica::report-chat', this.handleReport);
},
methods: {
+43 -28
View File
@@ -385,7 +385,7 @@
import extend from 'lodash/extend';
import groupUtilities from '@/mixins/groupsUtilities';
import styleHelper from '@/mixins/styleHelper';
import { mapState } from '@/libs/store';
import { mapState, mapGetters } from '@/libs/store';
import * as Analytics from '@/libs/analytics';
import startQuestModal from './startQuestModal';
import questDetailsModal from './questDetailsModal';
@@ -447,6 +447,7 @@ export default {
bronzeGuildBadgeIcon,
}),
members: [],
membersLoaded: false,
selectedQuest: {},
chat: {
submitDisable: false,
@@ -455,7 +456,12 @@ export default {
};
},
computed: {
...mapState({ user: 'user.data' }),
...mapState({
user: 'user.data',
}),
...mapGetters({
partyMembers: 'party:members',
}),
partyStore () {
return this.$store.state.party;
},
@@ -487,10 +493,15 @@ export default {
}
},
},
mounted () {
async mounted () {
if (this.isParty) this.searchId = 'party';
if (!this.searchId) this.searchId = this.groupId;
this.load();
await this.fetchGuild();
this.$root.$on('updatedGroup', this.onGroupUpdate);
},
beforeDestroy () {
this.$root.$off('updatedGroup', this.onGroupUpdate);
},
beforeRouteUpdate (to, from, next) {
this.$set(this, 'searchId', to.params.groupId);
@@ -501,19 +512,9 @@ export default {
acceptCommunityGuidelines () {
this.$store.dispatch('user:set', { 'flags.communityGuidelinesAccepted': true });
},
async load () {
if (this.isParty) {
this.searchId = 'party';
// @TODO: Set up from old client. Decide what we need and what we don't
// Check Desktop notifs
// Load invites
}
await this.fetchGuild();
this.$root.$on('updatedGroup', group => {
const updatedGroup = extend(this.group, group);
this.$set(this.group, updatedGroup);
});
onGroupUpdate (group) {
const updatedGroup = extend(this.group, group);
this.$set(this.group, updatedGroup);
},
/**
@@ -531,6 +532,26 @@ export default {
return this.$store.dispatch('members:getGroupMembers', payload);
},
showMemberModal () {
this.$store.state.memberModalOptions.loading = true;
if (this.isParty) {
this.membersLoaded = true;
this.members = this.partyMembers;
this.$store.state.memberModalOptions.loading = false;
} else if (!this.membersLoaded) {
this.membersLoaded = true;
this.loadMembers({
groupId: this.group._id,
includeAllPublicFields: true,
}).then(m => {
this.members.push(...m);
this.$store.state.memberModalOptions.loading = false;
});
} else {
this.$store.state.memberModalOptions.loading = false;
}
this.$root.$emit('habitica:show-member-modal', {
groupId: this.group._id,
group: this.group,
@@ -565,19 +586,13 @@ export default {
const groupId = this.searchId === 'party' ? this.user.party._id : this.searchId;
if (this.hasUnreadMessages(groupId)) {
// Delay by 1sec to make sure it returns after
// other requests that don't have the notification marked as read
setTimeout(() => {
this.$store.dispatch('chat:markChatSeen', { groupId });
this.$delete(this.user.newMessages, groupId);
}, 1000);
const notification = this.user
.notifications.find(n => n.type === 'NEW_CHAT_MESSAGE' && n.data.group.id === groupId);
const notificationId = notification && notification.id;
this.$store.dispatch('chat:markChatSeen', { groupId, notificationId });
}
this.members = await this.loadMembers({
groupId: this.group._id,
includeAllPublicFields: true,
});
},
// returns the notification id or false
hasUnreadMessages (groupId) {
if (this.user.newMessages[groupId]) return true;
@@ -99,14 +99,21 @@
</div>
</div>
</div>
<div v-if="selectedPage === 'members'">
<loading-gryphon v-if="loading" />
<div
v-if="selectedPage === 'members' && !loading"
:class="{'mt-1': invites.length === 0}"
>
<div
v-for="(member, index) in sortedMembers"
:key="member._id"
class="row"
>
<div class="col-11 no-padding-left">
<member-details :member="member" />
<member-details
:member="member"
:class-badge-position="'next-to-name'"
/>
</div>
<div class="col-1 actions">
<b-dropdown right="right">
@@ -201,7 +208,7 @@
class="row gradient"
></div>
</div>
<div v-if="selectedPage === 'invites'">
<div v-if="selectedPage === 'invites' && !loading">
<div
v-for="(member, index) in invites"
:key="member._id"
@@ -234,14 +241,6 @@
</div>
</div>
</div>
<div class="modal-footer">
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('close') }}
</button>
</div>
</b-modal>
</div>
</template>
@@ -254,11 +253,6 @@
box-shadow: 0 1px 2px 0 rgba(26, 24, 29, 0.24);
}
.modal-footer {
background-color: #edecee;
border-radius: 0 0 8px 8px;
}
.small-text, .character-name {
color: #878190;
}
@@ -270,6 +264,8 @@
.modal-body {
padding-left: 0;
padding-right: 0;
padding-bottom: 0;
padding-top: 0;
}
.member-details {
@@ -378,6 +374,7 @@ import isEmpty from 'lodash/isEmpty';
import { mapState } from '@/libs/store';
import removeMemberModal from '@/components/members/removeMemberModal';
import loadingGryphon from '@/components/ui/loadingGryphon';
import MemberDetails from '../memberDetails';
import removeIcon from '@/assets/members/remove.svg';
import messageIcon from '@/assets/members/message.svg';
@@ -388,6 +385,7 @@ export default {
components: {
MemberDetails,
removeMemberModal,
loadingGryphon,
},
props: ['hideBadge'],
data () {
@@ -474,6 +472,9 @@ export default {
challengeId () {
return this.$store.state.memberModalOptions.challengeId;
},
loading () {
return this.$store.state.memberModalOptions.loading;
},
sortedMembers () {
let sortedMembers = this.members.slice(); // shallow clone to avoid infinite loop
@@ -504,16 +505,6 @@ export default {
},
},
watch: {
groupId () {
// @TODO: We might not need this since groupId is computed now
this.getMembers();
},
challengeId () {
this.getMembers();
},
group () {
this.getMembers();
},
// Watches `searchTerm` and if present, performs a `searchMembers` action
// and usual `getMembers` otherwise
searchTerm () {
@@ -537,7 +528,7 @@ export default {
this.getMembers();
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica:show-member-modal');
},
methods: {
@@ -558,8 +549,9 @@ export default {
});
},
async getMembers () {
const { groupId } = this;
this.members = this.$store.state.memberModalOptions.viewingMembers;
const { groupId } = this;
if (groupId && groupId !== 'challenge') {
const invites = await this.$store.dispatch('members:getGroupInvites', {
groupId,
@@ -567,8 +559,6 @@ export default {
});
this.invites = invites;
}
this.members = this.$store.state.memberModalOptions.viewingMembers;
},
async clickMember (uid, forceShow) {
const user = this.$store.state.user.data;
@@ -209,7 +209,7 @@ export default {
this.$root.$on('selectQuest', this.selectQuest);
},
destroyed () {
beforeDestroy () {
this.$root.$off('selectQuest', this.selectQuest);
},
methods: {
@@ -222,8 +222,8 @@ export default {
this.$root.$emit('bv::show::modal', 'invite-modal');
});
},
destroyed () {
this.$root.off('inviteModal::inviteToGroup');
beforeDestroy () {
this.$root.$off('inviteModal::inviteToGroup');
},
methods: {
...mapActions({
@@ -250,6 +250,7 @@ export default {
groupId: party.data._id,
viewingMembers: this.partyMembers,
group: party.data,
fetchMoreMembers: p => this.$store.dispatch('members:getGroupMembers', p),
});
},
setPartyMembersWidth ($event) {
@@ -182,10 +182,10 @@ export default {
remove () {
if (this.notification.type === 'NEW_CHAT_MESSAGE') {
const groupId = this.notification.data.group.id;
this.$store.dispatch('chat:markChatSeen', { groupId });
if (this.user.newMessages[groupId]) {
this.$delete(this.user.newMessages, groupId);
}
this.$store.dispatch('chat:markChatSeen', {
groupId,
notificationId: this.notification.id,
});
} else {
this.readNotification({ notificationId: this.notification.id });
}
@@ -1,6 +1,6 @@
<template>
<base-notification
v-if="worldBoss.active"
v-if="worldBoss && worldBoss.active"
:can-remove="false"
:notification="{}"
:read-after-click="false"
@@ -11,10 +11,16 @@
class="background"
>
<div class="text">
<div class="title">
<div
v-once
class="title"
>
{{ $t('worldBoss') }}
</div>
<div class="sub-title">
<div
v-once
class="sub-title"
>
{{ $t('questDysheartenerText') }}
</div>
</div>
@@ -40,6 +46,7 @@
</div>
<div class="pending-damage">
<div
v-once
class="svg-icon"
v-html="icons.sword"
></div>
@@ -182,11 +189,13 @@ export default {
sword,
}),
questData,
worldBoss: {},
};
},
computed: {
...mapState({ user: 'user.data' }),
...mapState({
user: 'user.data',
worldBoss: 'worldState.data.worldBoss',
}),
bossHp () {
if (this.worldBoss && this.worldBoss.progress) {
return this.worldBoss.progress.hp;
@@ -195,8 +204,7 @@ export default {
},
},
async mounted () {
const result = await this.$store.dispatch('worldState:getWorldState');
this.worldBoss = result.worldBoss;
await this.$store.dispatch('worldState:getWorldState');
},
methods: {
action () {
@@ -124,7 +124,7 @@ export default {
mounted () {
this.$root.$on('hatchedPet::open', this.openDialog);
},
destroyed () {
beforeDestroy () {
this.$root.$off('hatchedPet::open', this.openDialog);
},
methods: {
@@ -102,7 +102,7 @@ export default {
mounted () {
this.$root.$on('habitica::mount-raised', this.openDialog);
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica::mount-raised', this.openDialog);
},
methods: {
@@ -3,6 +3,7 @@
class="create-dropdown"
:text="text"
no-flip="no-flip"
@show="$emit('opened')"
>
<b-dropdown-form
:disabled="false"
@@ -10,10 +11,14 @@
>
<input
v-model="searchTerm"
class="form-control"
class="form-control member-input"
type="text"
>
</b-dropdown-form>
<loading-gryphon
v-if="loading"
:height="32"
/>
<b-dropdown-item
v-for="member in memberResults"
:key="member._id"
@@ -25,13 +30,25 @@
</template>
<style lang="scss" scoped>
.create-dropdown ::v-deep form.b-dropdown-form {
padding-left: 8px;
padding-right: 8px;
}
.create-dropdown ::v-deep ul.dropdown-menu {
width: 100%;
}
</style>
<script>
// @TODO: how do we subclass this rather than type checking?
import challengeMemberSearchMixin from '@/mixins/challengeMemberSearch';
import loadingGryphon from '@/components/ui/loadingGryphon';
export default {
components: {
loadingGryphon,
},
mixins: [challengeMemberSearchMixin],
props: {
text: {
@@ -52,6 +69,11 @@ export default {
memberResults: [],
};
},
computed: {
loading () {
return this.$store.state.memberModalOptions.loading;
},
},
watch: {
memberResults () {
if (this.memberResults.length > 10) this.memberResults.length = 10;
@@ -226,8 +226,6 @@ export default {
beforeDestroy () {
this.$el.removeEventListener('selectstart', () => this.handleSelectStart());
this.$el.removeEventListener('mouseup', () => this.handleSelectChange());
},
destroyed () {
window.removeEventListener('scroll', this.handleScroll);
},
computed: {
@@ -817,10 +817,8 @@ export default {
break;
}
case 'CRON':
if (notification.data) {
if (notification.data.hp) this.hp(notification.data.hp, 'hp');
if (notification.data.mp && this.userHasClass) this.mp(notification.data.mp);
}
// Not needed because it's shown already by the userHp and userMp watchers
// Keeping an empty block so that it gets read
break;
case 'SCORED_TASK':
// Search if it is a read notification
@@ -125,7 +125,7 @@ export default {
});
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica::pay-with-amazon');
},
methods: {
@@ -79,7 +79,7 @@ export default {
this.$root.$emit('bv::show::modal', 'subscription-cancel-modal');
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica:cancel-subscription-confirm');
},
methods: {
@@ -108,7 +108,7 @@ export default {
this.$root.$emit('bv::show::modal', 'subscription-canceled-modal');
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica:subscription-canceled');
},
methods: {
@@ -237,7 +237,7 @@ export default {
this.$root.$emit('bv::show::modal', 'payments-success-modal');
});
},
destroyed () {
beforeDestroy () {
this.paymentData = {};
this.$root.$off('habitica:payments-success');
},
@@ -161,7 +161,7 @@
import _filter from 'lodash/filter';
import _map from 'lodash/map';
import _throttle from 'lodash/throttle';
import { mapState } from '@/libs/store';
import { mapState, mapGetters } from '@/libs/store';
import KeysToKennel from './keysToKennel';
import EquipmentSection from './equipmentSection';
@@ -221,8 +221,6 @@ export default {
hideLocked: false,
hidePinned: false,
broken: false,
};
},
computed: {
@@ -232,6 +230,9 @@ export default {
userStats: 'user.data.stats',
userItems: 'user.data.items',
}),
...mapGetters({
broken: 'worldState.brokenMarket',
}),
market () {
return shops.getMarketShop(this.user);
},
@@ -303,10 +304,7 @@ export default {
}, 250),
},
async mounted () {
const worldState = await this.$store.dispatch('worldState:getWorldState');
this.broken = worldState && worldState.worldBoss
&& worldState.worldBoss.extra && worldState.worldBoss.extra.worldDmg
&& worldState.worldBoss.extra.worldDmg.market;
await this.$store.dispatch('worldState:getWorldState');
},
methods: {
sellItem (itemScope) {
@@ -196,7 +196,7 @@ export default {
this.$root.$emit('bv::show::modal', 'sell-modal');
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('sellItem');
},
methods: {
@@ -456,7 +456,7 @@ import _sortBy from 'lodash/sortBy';
import _throttle from 'lodash/throttle';
import _groupBy from 'lodash/groupBy';
import _map from 'lodash/map';
import { mapState } from '@/libs/store';
import { mapState, mapGetters } from '@/libs/store';
import ShopItem from '../shopItem';
import Item from '@/components/inventory/item';
@@ -503,8 +503,6 @@ export default {
hideLocked: false,
hidePinned: false,
broken: false,
};
},
computed: {
@@ -514,6 +512,9 @@ export default {
userStats: 'user.data.stats',
userItems: 'user.data.items',
}),
...mapGetters({
broken: 'worldState.brokenQuests',
}),
shop () {
return shops.getQuestShop(this.user);
},
@@ -540,9 +541,7 @@ export default {
}, 250),
},
async mounted () {
const worldState = await this.$store.dispatch('worldState:getWorldState');
this.broken = worldState && worldState.worldBoss && worldState.worldBoss.extra
&& worldState.worldBoss.extra.worldDmg && worldState.worldBoss.extra.worldDmg.quests;
await this.$store.dispatch('worldState:getWorldState');
},
methods: {
questItems (category, sortBy, searchBy, hideLocked, hidePinned) {
@@ -373,7 +373,7 @@ import _sortBy from 'lodash/sortBy';
import _throttle from 'lodash/throttle';
import _groupBy from 'lodash/groupBy';
import _reverse from 'lodash/reverse';
import { mapState } from '@/libs/store';
import { mapState, mapGetters } from '@/libs/store';
import Checkbox from '@/components/ui/checkbox';
import PinBadge from '@/components/ui/pinBadge';
@@ -434,8 +434,6 @@ export default {
featuredGearBought: false,
backgroundUpdate: new Date(),
broken: false,
};
},
computed: {
@@ -444,6 +442,9 @@ export default {
user: 'user.data',
userStats: 'user.data.stats',
}),
...mapGetters({
broken: 'worldState.brokenSeasonalShop',
}),
usersOfficalPinnedItems () {
return getOfficialPinnedItems(this.user);
@@ -516,14 +517,11 @@ export default {
}, 250),
},
async mounted () {
const worldState = await this.$store.dispatch('worldState:getWorldState');
this.broken = worldState && worldState.worldBoss && worldState.worldBoss.extra
&& worldState.worldBoss.extra.worldDmg && worldState.worldBoss.extra.worldDmg.seasonalShop;
},
created () {
this.$root.$on('buyModal::boughtItem', () => {
this.backgroundUpdate = new Date();
});
await this.$store.dispatch('worldState:getWorldState');
},
beforeDestroy () {
this.$root.$off('buyModal::boughtItem');
@@ -395,7 +395,7 @@ export default {
this.searchTextThrottled = this.searchText.toLowerCase();
}, 250),
},
created () {
mounted () {
this.$root.$on('buyModal::boughtItem', () => {
this.backgroundUpdate = new Date();
});
@@ -91,7 +91,7 @@ export default {
brokenChallengeTask: {},
};
},
created () {
mounted () {
this.$root.$on('handle-broken-task', task => {
this.brokenChallengeTask = { ...task };
this.$root.$emit('bv::show::modal', 'broken-task-modal');
@@ -515,7 +515,7 @@ export default {
this.loadCompletedTodos();
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('buyModal::boughtItem');
if (this.type !== 'todo') return;
this.$root.$off(EVENTS.RESYNC_COMPLETED);
@@ -1323,7 +1323,7 @@ export default {
created () {
document.addEventListener('keyup', this.handleEsc);
},
destroyed () {
beforeDestroy () {
document.removeEventListener('keyup', this.handleEsc);
},
methods: {
@@ -91,7 +91,7 @@ export default {
mounted () {
document.documentElement.addEventListener('click', this._clickOutListener);
},
destroyed () {
beforeDestroy () {
document.removeEventListener('click', this._clickOutListener);
},
methods: {
@@ -0,0 +1,57 @@
<template>
<div class="loading-gryphon-wrapper">
<div
v-once
class="svg-icon loading-gryphon"
:style="{width: `${width}px`, height: `${height}px`}"
v-html="icons.gryphon"
></div>
</div>
</template>
<style lang='scss' scoped>
.loading-gryphon-wrapper {
width: 100%;
padding-top: 72px;
padding-bottom: 72px;
}
.loading-gryphon {
color: #6133b4;
margin: 0 auto;
animation: pulsate 2s linear infinite;
}
@keyframes pulsate {
from { opacity: 1; }
50% { opacity: 0.5; }
to { opacity: 1; }
}
</style>
<script>
import gryphon from '@/assets/svg/gryphon.svg';
export default {
props: {
height: {
type: Number,
default: 48,
},
},
data () {
return {
icons: Object.freeze({
gryphon,
}),
};
},
computed: {
// The original SVG is 70px tall and 64px wide, we calculate the width based on that
// in order to keep the right proportions
width () {
return (this.height / 70) * 64;
},
},
};
</script>
@@ -4,6 +4,11 @@
class="profile"
>
<div class="header">
<span
class="close-icon svg-icon inline icon-10"
@click="close()"
v-html="icons.close"
></span>
<div class="profile-actions">
<router-link
:to="{ path: '/private-messages', query: { uuid: user._id } }"
@@ -559,6 +564,7 @@
.achievement-wrapper {
width: 94px;
min-width: 94px !important;
max-width: 94px;
margin-right: 12px;
margin-left: 12px;
@@ -717,6 +723,7 @@ import lock from '@/assets/svg/lock.svg';
import challenge from '@/assets/svg/challenge.svg';
import member from '@/assets/svg/member-icon.svg';
import staff from '@/assets/svg/tier-staff.svg';
import svgClose from '@/assets/svg/close.svg';
// @TODO: EMAILS.COMMUNITY_MANAGER_EMAIL
const COMMUNITY_MANAGER_EMAIL = 'admin@habitica.com';
@@ -742,6 +749,7 @@ export default {
lock,
member,
staff,
close: svgClose,
}),
adminToolsLoaded: false,
userIdToMessage: '',
@@ -987,6 +995,9 @@ export default {
const status = this.achievementsCategories[categoryKey].open;
this.achievementsCategories[categoryKey].open = !status;
},
close () {
this.$root.$emit('bv::hide::modal', 'profile');
},
},
};
</script>
@@ -45,7 +45,7 @@ export default {
this.$root.$emit('bv::show::modal', 'profile');
});
},
destroyed () {
beforeDestroy () {
this.$root.$off('habitica:show-profile');
},
methods: {
+19 -4
View File
@@ -6,12 +6,14 @@ import axios from 'axios';
export function asyncResourceFactory () {
return {
loadingStatus: 'NOT_LOADED', // NOT_LOADED, LOADING, LOADED
appVersionOnLoad: null, // record the server app version the last time the resource was loaded
data: null,
};
}
export function loadAsyncResource ({
store, path, url, deserialize, forceLoad = false,
store, path, url, deserialize,
forceLoad = false, reloadOnAppVersionChange = false,
}) {
if (!store) throw new Error('"store" is required and must be the application store.');
if (!path) throw new Error('The path to the resource in the application state is required.');
@@ -22,7 +24,16 @@ export function loadAsyncResource ({
if (!resource) throw new Error(`No resouce found at path "${path}".`);
const { loadingStatus } = resource;
if (loadingStatus === 'LOADED' && !forceLoad) {
// Has the server been updated since we last loaded this resource?
const appVersionHasChanged = loadingStatus === 'LOADED'
&& store.state.serverAppVersion
&& store.state.serverAppVersion !== resource.appVersionOnLoad;
let shouldUpdate = false;
if (forceLoad) shouldUpdate = true;
if (appVersionHasChanged && reloadOnAppVersionChange) shouldUpdate = true;
if (loadingStatus === 'LOADED' && !shouldUpdate) {
return Promise.resolve(resource);
} if (loadingStatus === 'LOADING') {
return new Promise((resolve, reject) => {
@@ -34,15 +45,19 @@ export function loadAsyncResource ({
return reject(); // TODO add reason?
});
});
} if (loadingStatus === 'NOT_LOADED' || forceLoad) {
return axios.get(url).then(response => { // TODO support more params
} if (loadingStatus === 'NOT_LOADED' || shouldUpdate) { // @TODO set loadingStatus back to LOADING?
return axios.get(url).then(response => { // @TODO support more params
resource.loadingStatus = 'LOADED';
// deserialize can be a promise
return Promise.resolve(deserialize(response)).then(deserializedData => {
resource.data = deserializedData;
// record the app version when the resource was loaded
// allows reloading if the app version has changed
resource.appVersionOnLoad = store.state.serverAppVersion;
return resource;
});
});
}
return Promise.reject(new Error(`Invalid loading status "${loadingStatus} for resource at "${path}".`));
}
-1
View File
@@ -34,7 +34,6 @@ export function setUpLogging () { // eslint-disable-line import/prefer-default-e
_LTracker.push({
err,
vm,
info,
});
};
@@ -662,8 +662,9 @@ export default {
this.selectConversation(this.initiatedConversation.uuid);
}
},
destroyed () {
beforeDestroy () {
this.$root.$off(EVENTS.RESYNC_COMPLETED);
this.$root.$off(EVENTS.PM_REFRESH);
},
computed: {
...mapState({ user: 'user.data' }),
+9 -1
View File
@@ -1,4 +1,5 @@
import axios from 'axios';
import Vue from 'vue';
import * as Analytics from '@/libs/analytics';
export async function getChat (store, payload) {
@@ -70,8 +71,15 @@ export async function clearFlagCount (store, payload) {
}
export async function markChatSeen (store, payload) {
if (store.state.user.newMessages) delete store.state.user.newMessages[payload.groupId];
const url = `/api/v4/groups/${payload.groupId}/chat/seen`;
const response = await axios.post(url);
if (store.state.user.data.newMessages[payload.groupId]) {
Vue.delete(store.state.user.data.newMessages, payload.groupId);
}
if (payload.notificationId) {
store.state.notificationsRemoved.push(payload.notificationId);
}
return response.data.data;
}
+2 -1
View File
@@ -74,8 +74,9 @@ export async function join (store, payload) {
if (invitationI !== -1) invitations.parties.splice(invitationI, 1);
user.party._id = groupId;
Analytics.updateUser({ partyID: groupId });
// load the party members so that they get shown in the header
store.dispatch('party:getMembers');
}
return response.data.data;
+1 -1
View File
@@ -15,7 +15,7 @@ import * as tags from './tags';
import * as hall from './hall';
import * as shops from './shops';
import * as snackbars from './snackbars';
import * as worldState from './world-state';
import * as worldState from './worldState';
// Actions should be named as 'actionName' and can be accessed as 'namespace:actionName'
// Example: fetch in user.js -> 'user:fetch'
@@ -3,6 +3,7 @@ import axios from 'axios';
export async function readNotification (store, payload) {
const url = `/api/v4/notifications/${payload.notificationId}/read`;
const response = await axios.post(url);
store.state.notificationsRemoved.push(payload.notificationId);
return response.data.data;
}
@@ -11,6 +12,7 @@ export async function readNotifications (store, payload) {
const response = await axios.post(url, {
notificationIds: payload.notificationIds,
});
store.state.notificationsRemoved.push(...payload.notificationIds);
return response.data.data;
}
@@ -1,7 +0,0 @@
import axios from 'axios';
export async function getWorldState () { // eslint-disable-line import/prefer-default-export
const url = '/api/v4/world-state';
const response = await axios.get(url);
return response.data.data;
}
@@ -0,0 +1,14 @@
import { loadAsyncResource } from '@/libs/asyncResource';
export async function getWorldState (store, options = {}) {
return loadAsyncResource({
store,
path: 'worldState',
url: '/api/v4/world-state',
deserialize (response) {
return response.data.data;
},
forceLoad: options.forceLoad,
reloadOnAppVersionChange: true, // reload when the server has been updated
});
}
@@ -4,6 +4,7 @@ import * as shops from './shops';
import * as tasks from './tasks';
import * as party from './party';
import * as members from './members';
import * as worldState from './worldState';
// Getters should be named as 'getterName' and can be accessed as 'namespace:getterName'
// Example: gems in user.js -> 'user:gems'
@@ -14,6 +15,7 @@ const getters = flattenAndNamespace({
party,
members,
shops,
worldState,
});
export default getters;
@@ -0,0 +1,23 @@
function getWorldDamage (store) {
const worldState = store.state.worldState.data;
return worldState
&& worldState.worldBoss
&& worldState.worldBoss.extra
&& worldState.worldBoss.extra.worldDmg;
}
export function brokenSeasonalShop (store) {
const worldDmg = getWorldDamage(store);
return worldDmg && worldDmg.seasonalShop;
}
export function brokenMarket (store) {
const worldDmg = getWorldDamage(store);
return worldDmg && worldDmg.market;
}
export function brokenQuests (store) {
const worldDmg = getWorldDamage(store);
return worldDmg && worldDmg.quests;
}
+12 -2
View File
@@ -50,12 +50,20 @@ export default function () {
actions,
getters,
state: {
serverAppVersion: '',
serverAppVersion: null,
title: 'Habitica',
isUserLoggedIn,
isUserLoaded: false, // Means the user and the user's tasks are ready
// Means the user and the user's tasks are ready
// @TODO use store.user.loaded since it's an async resource?
isUserLoaded: false,
isAmazonReady: false, // Whether the Amazon Payments lib can be used
user: asyncResourceFactory(),
// Keep track of the ids of notifications that have been removed
// to make sure they don't get shown again. It happened due to concurrent requests
// which in some cases could result in a read notification showing up again
// see https://github.com/HabitRPG/habitica/issues/9242
notificationsRemoved: [],
worldState: asyncResourceFactory(),
credentials: isUserLoggedIn ? {
API_ID: AUTH_SETTINGS.auth.apiId,
API_TOKEN: AUTH_SETTINGS.auth.apiToken,
@@ -65,6 +73,7 @@ export default function () {
// in app.vue
browserTimezoneOffset,
tasks: asyncResourceFactory(), // user tasks
// @TODO use asyncresource?
completedTodosStatus: 'NOT_LOADED',
party: asyncResourceFactory(),
partyMembers: asyncResourceFactory(),
@@ -105,6 +114,7 @@ export default function () {
groupId: '',
challengeId: '',
group: {},
loading: false,
},
openedItemRows: [],
spellOptions: {
@@ -123,6 +123,56 @@ describe('async resource', () => {
expect(axios.get).to.have.been.calledOnce;
});
describe('reloadOnAppVersionChange', async () => {
let store;
beforeEach(() => {
store = generateStore();
store.state.worldState.loadingStatus = 'LOADED';
store.state.serverAppVersion = 1;
store.state.worldState.appVersionOnLoad = 1;
});
it('load the resource if it is loaded but the appVersion has changed', async () => {
store.state.serverAppVersion = 2;
sandbox.stub(axios, 'get').withArgs('/api/v4/world-state').returns(Promise.resolve({
data: { data: { _id: 1 } },
}));
const resource = await loadAsyncResource({
store,
path: 'worldState',
url: '/api/v4/world-state',
reloadOnAppVersionChange: true,
deserialize (response) {
return response.data.data;
},
});
expect(resource).to.equal(store.state.worldState);
expect(resource.loadingStatus).to.equal('LOADED');
expect(resource.data._id).to.equal(1);
expect(axios.get).to.have.been.calledOnce;
});
it('does not load the resource if it is loaded but the appVersion has changed', async () => {
sandbox.stub(axios, 'get').returns(Promise.resolve({ data: { data: { _id: 1 } } }));
const resource = await loadAsyncResource({
store,
path: 'worldState',
url: '/api/v4/world-state',
reloadOnAppVersionChange: true,
deserialize (response) {
return response.data.data;
},
});
expect(resource).to.equal(store.state.worldState);
expect(axios.get).to.not.have.been.called;
});
});
it('does not send multiple requests if the resource is being loaded', async () => {
const store = generateStore();
store.state.user.loadingStatus = 'LOADING';
+4 -1
View File
@@ -78,5 +78,8 @@
"achievementHatchedPet": "Излюпи Животно",
"viewAchievements": "Постижения",
"letsGetStarted": "Нека да започнем!",
"onboardingProgress": "<%= percentage %>% напредък"
"onboardingProgress": "<%= percentage %>% напредък",
"achievementBareNecessitiesModalText": "Завършихте мисиите за Маймуна, Ленивец и Фиданка!",
"achievementBareNecessitiesText": "Завършили са всички мисии за Маймуна, Ленивец и Фиданка.",
"achievementBareNecessities": "От първа необходимост"
}
+34 -2
View File
@@ -413,7 +413,7 @@
"backgroundMedievalKitchenNotes": "Сгответе страшна буря в Средновековна Кухня.",
"backgroundMedievalKitchenText": "Средновековна Кухня",
"backgrounds022019": "Комплект 57: Открит Февруари 2019",
"backgroundAmongGiantAnemonesText": "Измежду Гигантски Актиниѝ",
"backgroundAmongGiantAnemonesText": "Сред Гигантски Анемони",
"backgroundFlyingOverTropicalIslandsNotes": "Позволете на гледката да ви отнеме дъхът, докату Прелетявате над Тропически Острови.",
"backgroundFlyingOverTropicalIslandsText": "Прелет над Тропически Острови",
"backgroundLakeWithFloatingLanternsNotes": "Наблюдавайте звездите от фестивалната атмосфера на Езеро с Плуващи Фенери.",
@@ -449,5 +449,37 @@
"backgrounds032019": "КОМПЛЕКТ 58: Открит Март 2019",
"backgroundValentinesDayFeastingHallNotes": "Почуствайте любовта в Свети Валентинска Банкетна Зала.",
"backgroundValentinesDayFeastingHallText": "Свети Валентинска Банкетна Зала",
"backgroundOldFashionedBakeryNotes": "Насладете се на апетитната миризмата отвън една Старовремна Пекарня."
"backgroundOldFashionedBakeryNotes": "Насладете се на апетитната миризмата отвън една Старовремна Пекарня.",
"backgrounds122019": "КОМПЛЕКТ 67: декември 2019",
"backgroundPotionShopNotes": "Намерете елексир за всяко заболяване в Магазин за Отвари.",
"backgroundPotionShopText": "Магазин за Отвари",
"backgroundFlyingInAThunderstormNotes": "Гонете Буйна Гръмотевична Буря колкото близко смеете.",
"backgroundFlyingInAThunderstormText": "Буйна Гръмотевична Буря",
"backgroundFarmersMarketNotes": "Пазарувайте най-свежите храни в Фермерски Пазар.",
"backgroundFarmersMarketText": "Фермерски Пазар",
"backgrounds112019": "КОМПЛЕКТ 66: ноември 2019",
"backgroundMonsterMakersWorkshopNotes": "Експериментирайте с дискредитирани науки в Работилницата на Създател на Чудовища.",
"backgroundMonsterMakersWorkshopText": "Работилницата на Създател на Чудовища",
"backgroundPumpkinCarriageNotes": "Возете се във вълшебен Тиквен Файтон преди часовника да удари полунощ.",
"backgroundPumpkinCarriageText": "Тиквен Файтон",
"backgroundFoggyMoorNotes": "Внимавайте къде стъпвате като прекосявате Мъгливо Тресавище.",
"backgroundFoggyMoorText": "Мъгливо Тресавище",
"backgrounds102019": "КОМПЛЕКТ 65: октомври 2019",
"backgroundInAClassroomNotes": "Абсорбирайте знания от вашите ментори в Класна Стая.",
"backgroundInAClassroomText": "Класна Стая",
"backgroundInAnAncientTombNotes": "Изправете се пред тайните на Древна Гробница.",
"backgroundInAnAncientTombText": "Древна Гробница",
"backgroundAutumnFlowerGardenNotes": "Поемете топлината на една Есенна Цветна Градина.",
"backgroundAutumnFlowerGardenText": "Есенна Цветна Градина",
"backgrounds092019": "КОМПЛЕКТ 64: септември 2019",
"backgroundTreehouseNotes": "Пошляйте се в дървесно скривалище само за вас, в собствената си Къща на Дърво.",
"backgroundTreehouseText": "Къща на Дърво",
"backgroundGiantDandelionsNotes": "Шлайте се сред Гигантски Глухарчета.",
"backgroundGiantDandelionsText": "Гигантски Глухарчета",
"backgroundAmidAncientRuinsNotes": "Застанете в почит към мистериозното минало Сред Древни Руини.",
"backgroundAmongGiantAnemonesNotes": "Експлорирайте рифовия живот, защитен от хищници Сред Гигантски Анемони.",
"backgroundAmidAncientRuinsText": "Сред Древни Руини",
"backgrounds082019": "КОМПЛЕКТ 63: август 2019",
"backgroundHolidayMarketNotes": "Намерете перфектните подаръци и декорации в Празничния Пазар.",
"backgroundHolidayMarketText": "Празничен Пазар"
}
+7 -3
View File
@@ -104,7 +104,7 @@
"allocatePerPop": "Добавяне на точка към Усет",
"allocateInt": "Разпределени точки към Интелигентност:",
"allocateIntPop": "Добавяне на точка към Интелигентност",
"noMoreAllocate": "След като достигнахте ниво 100, вече няма да получавате повече показателни точки. Може да продължавате да вдигате нива или да започнете ново приключение от ниво 1, използвайки <a href='http://habitica.fandom.com/wiki/Orb_of_Rebirth' target='_blank'>Кълбото на прераждането</a>, вече достъпно безплатно на пазара.",
"noMoreAllocate": "След като достигнахте ниво 100, вече няма да получавате повече показателни точки. Може да продължавате да вдигате нива или да започнете ново приключение от ниво 1, използвайки <a href='http://habitica.fandom.com/wiki/Orb_of_Rebirth' target='_blank'>Кълбото на прераждането</a>!",
"stats": "Показатели",
"achievs": "Постижения",
"strength": "Сила",
@@ -156,7 +156,7 @@
"optOutOfClasses": "Отказване",
"optOutOfPMs": "Отказване",
"chooseClass": "Изберете клас",
"chooseClassLearnMarkdown": "[Научете повече относно класовата система на Хабитика](http://habitica.fandom.com/wiki/Class_System)",
"chooseClassLearnMarkdown": "[Научете повече относно класовата система на Хабитика](https://habitica.fandom.com/wiki/Class_System)",
"optOutOfClassesText": "Не Ви се занимава с класове? Искате да изберете по-късно? Откажете се от тях — ще бъдете воин без специални умения. Можете да прочетете относно класовата система по-късно в уикито, както и да включите класовете по всяко време от Потребителската иконка -> Настройки.",
"selectClass": "Избиране на <%= heroClass %>",
"select": "Избиране",
@@ -224,5 +224,9 @@
"mainHand": "Основна ръка",
"offHand": "Страничен",
"statPoints": "Показателни точки",
"pts": "точки"
"pts": "точки",
"chatCastSpellUser": "<%= username %> използва заклинанието <%= spell %> върху <%= target %>.",
"chatCastSpellParty": "<%= username %> използва заклинанието <%= spell %> върху групата.",
"purchasePetItemConfirm": "Тази покупка би надвишила броя на предметите, които са ви нужни за да излюпите всички възможни <% = itemText%> любимци. Сигурни ли сте?",
"purchaseForGold": "Купуване за <%= cost %> Злато?"
}

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