Orb of Rebirth Updates (Count usage) (#15629)

* Update orb of rebirth to count every usage

* Orb of rebirth modal UI updates

* Fix rebirth modal showing again after page refresh

* remove unused MAX_LEVEL

* scale orb of rebirth on modal

* UI & wording updates for Orb of Rebirth

* UI & wording updates for Orb of Rebirth cont.

* Orb of rebirth UI tweaks

* Orb of rebirth UI tweaks

* Orb of Rebirth modal UI tweak

* Extend modal waves

* Continued Orb of Rebirth UI Updates

* Orb of rebirth margin tweak

* rebirth-orb asset
This commit is contained in:
Fiz
2026-03-12 14:51:48 -05:00
committed by GitHub
parent 8c90e5472b
commit 74fc543ef2
8 changed files with 412 additions and 72 deletions
@@ -1,53 +1,228 @@
<template>
<b-modal
id="rebirth"
:title="$t('modalAchievement')"
size="md"
:hide-footer="true"
size="sm"
:hide-header="true"
>
<div class="modal-body">
<div class="col-12">
<!-- @TODO: +achievementAvatar('sun',0)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center">
<div v-if="user.achievements.rebirthLevel < 100">
{{ $t('rebirthAchievement', {
number: user.achievements.rebirths,
level: user.achievements.rebirthLevel}) }}
</div><div v-if="user.achievements.rebirthLevel >= 100">
{{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
</div><br><button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
<div
class="close-x"
@click.stop="close()"
>
<div
class="svg-icon svg-close"
v-html="icons.close"
></div>
</div>
<div class="content text-center">
<h2
v-once
class="header"
>
{{ $t('rebirthNewAchievement') }}
</h2>
<div class="d-flex align-items-center justify-content-center icon-area">
<div
v-once
class="svg-icon sparkles mirror"
v-html="icons.starGroup"
></div>
<Sprite
class="achievement-icon"
image-name="achievement-sun2x"
/>
<div
v-once
class="svg-icon sparkles"
v-html="icons.starGroup"
></div>
</div>
</div><achievement-footer />
<p class="subtitle">
{{ $t('rebirthNewAdventure') }}
</p>
<p
class="description"
v-html="achievementText"
></p>
<p
v-once
class="stack-info"
>
{{ $t('rebirthStackInfo') }}
</p>
<button
v-once
class="btn btn-primary"
@click="close()"
>
{{ $t('onwards') }}
</button>
</div>
<div
slot="modal-footer"
class="footer-wave"
v-html="icons.purpleWaves"
></div>
</b-modal>
</template>
<style scoped>
.avatar {
width: 140px;
margin: 0 auto;
margin-bottom: 1.5em;
margin-top: 1.5em;
<style lang="scss">
@import '@/assets/scss/colors.scss';
#rebirth {
.modal-dialog {
width: 330px;
}
.modal-content {
border: none;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 14px 28px 0 rgba($black, 0.24), 0 10px 10px 0 rgba($black, 0.28);
}
.modal-body {
padding: 0;
}
.modal-footer {
padding: 0;
border-top: none;
border-radius: 0;
margin: 0;
line-height: 0;
}
}
</style>
<style lang="scss" scoped>
@import '@/assets/scss/colors.scss';
.content {
padding: 24px 24px 0;
}
.header {
font-size: 1.25rem;
line-height: 1.4;
color: $purple-200;
margin-top: 8px;
margin-bottom: 16px;
}
.icon-area {
margin-bottom: 16px;
}
.sparkles {
width: 40px;
height: 64px;
&.mirror {
transform: scaleX(-1);
}
}
.close-x {
position: absolute;
right: 16px;
top: 16px;
cursor: pointer;
z-index: 2;
&:hover .svg-close {
opacity: 0.75;
}
.svg-close {
width: 16px;
height: 16px;
opacity: 0.5;
transition: opacity 0.2s ease;
pointer-events: none;
}
}
.achievement-icon {
margin: 0 24px;
}
.subtitle {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
line-height: 24px;
letter-spacing: 0;
margin-bottom: 12px;
color: $gray-10;
}
.description {
font-size: 0.875rem;
line-height: 1.71;
margin-bottom: 12px;
color: $gray-50;
}
.stack-info {
font-size: 0.875rem;
line-height: 1.71;
color: $gray-50;
margin-bottom: 24px;
}
.btn-primary {
margin-bottom: 8px;
}
.footer-wave {
width: 100%;
::v-deep svg {
display: block;
width: calc(100% + 8px);
height: auto;
margin: 0 -4px -4px;
}
}
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import closeIcon from '@/assets/svg/close.svg?raw';
import Sprite from '@/components/ui/sprite';
import starGroup from '@/assets/svg/star-group.svg?raw';
import purpleWaves from '@/assets/svg/purple-waves.svg?raw';
import { mapState } from '@/libs/store';
export default {
components: {
achievementFooter,
achievementAvatar,
Sprite,
},
data () {
return {
icons: Object.freeze({
starGroup,
purpleWaves,
close: closeIcon,
}),
};
},
computed: {
...mapState({ user: 'user.data' }),
achievementText () {
const rebirths = this.user.achievements.rebirths || 0;
const level = this.user.achievements.rebirthLevel || 0;
if (level >= 100) {
return this.$t('rebirthAchievement100', { number: rebirths, level });
}
if (rebirths === 1) {
return this.$t('rebirthAchievement', { number: rebirths, level });
}
return this.$t('rebirthAchievementPlural', { number: rebirths, level });
},
},
methods: {
close () {
@@ -1,41 +1,186 @@
<template>
<b-modal
id="rebirth-enabled"
:title="$t('rebirthNew')"
size="md"
:hide-footer="true"
size="sm"
:hide-header="true"
>
<div class="modal-body">
<div class="col-12">
<div class="rebirth_orb"></div>
<p>
<span>{{ $t('rebirthUnlock') }}</span>
</p>
</div>
<div
class="close-x"
@click.stop="close()"
>
<div
class="svg-icon svg-close"
v-html="icons.close"
></div>
</div>
<div class="modal-footer">
<div class="col-12 text-center">
<button
class="btn btn-primary"
@click="close()"
<div class="content text-center">
<h2
v-once
class="header"
>
{{ $t('rebirthUnlockedNewItem') }}
</h2>
<div class="d-flex align-items-center justify-content-center icon-area">
<div
v-once
class="svg-icon sparkles mirror"
v-html="icons.starGroup"
></div>
<img
class="orb-icon"
src="@/assets/images/rebirth-orb.png"
alt="Orb of Rebirth"
>
{{ $t('close') }}
</button>
<div
v-once
class="svg-icon sparkles"
v-html="icons.starGroup"
></div>
</div>
<p
v-once
class="subtitle"
>
{{ $t('rebirthUnlockedOrb') }}
</p>
<p
v-once
class="description"
>
{{ $t('rebirthUnlockedDesc') }}
</p>
<button
v-once
class="btn btn-primary"
@click="close()"
>
{{ $t('onwards') }}
</button>
</div>
<div
slot="modal-footer"
class="clearfix"
></div>
</b-modal>
</template>
<style scoped>
.rebirth_orb {
margin: 0 auto;
<style lang="scss">
@import '@/assets/scss/colors.scss';
#rebirth-enabled {
.modal-dialog {
width: 330px;
}
.modal-content {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 14px 28px 0 rgba($black, 0.24), 0 10px 10px 0 rgba($black, 0.28);
}
.modal-body {
padding: 0;
}
.modal-footer {
padding: 0;
border-top: none;
}
}
</style>
<style lang="scss" scoped>
@import '@/assets/scss/colors.scss';
.content {
padding: 24px 24px 0;
}
.header {
font-size: 1.25rem;
line-height: 1.4;
color: $purple-200;
margin-top: 8px;
margin-bottom: 12px;
}
.icon-area {
margin-bottom: 12px;
}
.sparkles {
width: 40px;
height: 64px;
&.mirror {
transform: scaleX(-1);
}
}
.close-x {
position: absolute;
right: 16px;
top: 16px;
cursor: pointer;
z-index: 2;
&:hover .svg-close {
opacity: 0.75;
}
.svg-close {
width: 16px;
height: 16px;
opacity: 0.5;
transition: opacity 0.2s ease;
pointer-events: none;
}
}
.orb-icon {
width: 62px;
height: 62px;
margin: 0 24px;
image-rendering: pixelated;
}
.subtitle {
font-family: 'Roboto', sans-serif;
font-weight: 700;
font-style: normal;
font-size: 14px;
line-height: 24px;
letter-spacing: 0;
margin-bottom: 12px;
color: $gray-50;
}
.description {
font-size: 0.875rem;
line-height: 1.71;
margin-bottom: 24px;
color: $gray-100;
}
.btn-primary {
margin-bottom: 24px;
}
</style>
<script>
import closeIcon from '@/assets/svg/close.svg?raw';
import starGroup from '@/assets/svg/star-group.svg?raw';
import { mapState } from '@/libs/store';
export default {
data () {
return {
icons: Object.freeze({
starGroup,
close: closeIcon,
}),
};
},
computed: {
...mapState({ user: 'user.data' }),
},
@@ -727,14 +727,14 @@ export default {
this.$root.$emit('habitica:won-challenge', notification);
break;
case 'REBIRTH_ACHIEVEMENT':
if (localStorage.getItem('show-rebirth-confirmation') === 'true') {
markAsRead = false;
} else if (!this.isInitialLoadComplete) {
this.pendingRebirthNotification = notification;
markAsRead = false;
} else {
this.playSound('Achievement_Unlocked');
this.$root.$emit('bv::show::modal', 'rebirth');
if (localStorage.getItem('show-rebirth-confirmation') !== 'true') {
if (!this.isInitialLoadComplete) {
this.pendingRebirthNotification = notification;
markAsRead = false;
} else {
this.playSound('Achievement_Unlocked');
this.$root.$emit('bv::show::modal', 'rebirth');
}
}
break;
case 'STREAK_ACHIEVEMENT':