summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--packages/backend/src/core/AchievementService.ts2
-rw-r--r--packages/frontend/src/components/mfm.ts6
-rw-r--r--packages/frontend/src/pages/about-misskey.vue117
-rw-r--r--packages/frontend/src/pages/about.vue9
-rw-r--r--packages/frontend/src/scripts/achievements.ts15
-rw-r--r--packages/frontend/src/scripts/mfm-tags.ts2
6 files changed, 108 insertions, 43 deletions
diff --git a/packages/backend/src/core/AchievementService.ts b/packages/backend/src/core/AchievementService.ts
index be763e4629..5fd9c451ce 100644
--- a/packages/backend/src/core/AchievementService.ts
+++ b/packages/backend/src/core/AchievementService.ts
@@ -62,12 +62,14 @@ const ACHIEVEMENT_TYPES = [
'collectAchievements30',
'viewAchievements3min',
'iLoveMisskey',
+ 'foundTreasure',
'client30min',
'noteDeletedWithin1min',
'postedAtLateNight',
'postedAt0min0sec',
'selfQuote',
'htl20npm',
+ 'viewInstanceChart',
'outputHelloWorldOnScratchpad',
'open3windows',
'driveFolderCircularReference',
diff --git a/packages/frontend/src/components/mfm.ts b/packages/frontend/src/components/mfm.ts
index 9421625c9e..91875de9cf 100644
--- a/packages/frontend/src/components/mfm.ts
+++ b/packages/frontend/src/components/mfm.ts
@@ -200,6 +200,12 @@ export default defineComponent({
style = `transform: translateX(${x}em) translateY(${y}em);`;
break;
}
+ case 'scale': {
+ const x = Math.min(parseInt(token.props.args.x ?? '1'), 5);
+ const y = Math.min(parseInt(token.props.args.y ?? '1'), 5);
+ style = `transform: scale(${x}, ${y});`;
+ break;
+ }
case 'fg': {
let color = token.props.args.color;
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index 1c3535a833..82f4e30a45 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -4,11 +4,14 @@
<div style="overflow: clip;">
<MkSpacer :content-max="600" :margin-min="20">
<div class="_gaps_m znqjceqz">
- <div ref="containerEl" v-panel class="about" :class="{ playing: easterEggEngine != null }">
- <img src="/client-assets/about-icon.png" alt="" class="icon" draggable="false" @load="iconLoaded" @click="gravity"/>
- <div class="misskey">Misskey</div>
- <div class="version">v{{ version }}</div>
- <span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :is-reaction="false" :normal="true" :no-style="true"/></span>
+ <div v-panel class="about">
+ <div ref="containerEl" class="container" :class="{ playing: easterEggEngine != null }">
+ <img src="/client-assets/about-icon.png" alt="" class="icon" draggable="false" @load="iconLoaded" @click="gravity"/>
+ <div class="misskey">Misskey</div>
+ <div class="version">v{{ version }}</div>
+ <span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :is-reaction="false" :normal="true" :no-style="true"/></span>
+ </div>
+ <button v-if="thereIsTreasure" class="_button treasure" @click="getTreasure"><img src="/fluent-emoji/1f3c6.png" class="treasureImg"></button>
</div>
<div style="text-align: center;">
{{ i18n.ts._aboutMisskey.about }}<br><a href="https://misskey-hub.net/docs/misskey.html" target="_blank" class="_link">{{ i18n.ts.learnMore }}</a>
@@ -70,6 +73,8 @@ import { i18n } from '@/i18n';
import { defaultStore } from '@/store';
import * as os from '@/os';
import { definePageMetadata } from '@/scripts/page-metadata';
+import { claimAchievement, claimedAchievements } from '@/scripts/achievements';
+import { $i } from '@/account';
const patrons = [
'まっちゃとーにゅ',
@@ -152,6 +157,8 @@ const patrons = [
'pixeldesu',
];
+let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
+
let easterEggReady = false;
let easterEggEmojis = $ref([]);
let easterEggEngine = $ref(null);
@@ -187,6 +194,11 @@ function iLoveMisskey() {
});
}
+function getTreasure() {
+ thereIsTreasure = false;
+ claimAchievement('foundTreasure');
+}
+
onBeforeUnmount(() => {
if (easterEggEngine) {
easterEggEngine.stop();
@@ -207,52 +219,77 @@ definePageMetadata({
.znqjceqz {
> .about {
position: relative;
- text-align: center;
- padding: 16px;
border-radius: var(--radius);
- &.playing {
- &, * {
- user-select: none;
- }
-
- * {
- will-change: transform;
- }
+ > .treasure {
+ position: absolute;
+ top: 60px;
+ left: 0;
+ right: 0;
+ margin: 0 auto;
+ width: min-content;
- > .emoji {
- visibility: visible;
+ > .treasureImg {
+ width: 25px;
+ vertical-align: bottom;
}
}
- > .icon {
- display: block;
- width: 80px;
- margin: 0 auto;
- border-radius: 16px;
- }
+ > .container {
+ position: relative;
+ text-align: center;
+ padding: 16px;
- > .misskey {
- margin: 0.75em auto 0 auto;
- width: max-content;
- }
+ &.playing {
+ &, * {
+ user-select: none;
+ }
- > .version {
- margin: 0 auto;
- width: max-content;
- opacity: 0.5;
- }
+ * {
+ will-change: transform;
+ }
- > .emoji {
- position: absolute;
- top: 0;
- left: 0;
- visibility: hidden;
+ > .emoji {
+ visibility: visible;
+ }
+ }
+
+ > .icon {
+ display: block;
+ width: 80px;
+ margin: 0 auto;
+ border-radius: 16px;
+ position: relative;
+ z-index: 1;
+ }
+
+ > .misskey {
+ margin: 0.75em auto 0 auto;
+ width: max-content;
+ position: relative;
+ z-index: 1;
+ }
+
+ > .version {
+ margin: 0 auto;
+ width: max-content;
+ opacity: 0.5;
+ position: relative;
+ z-index: 1;
+ }
> .emoji {
- pointer-events: none;
- font-size: 24px;
- width: 24px;
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ visibility: hidden;
+
+ > .emoji {
+ pointer-events: none;
+ font-size: 24px;
+ width: 24px;
+ }
}
}
}
diff --git a/packages/frontend/src/pages/about.vue b/packages/frontend/src/pages/about.vue
index 4d971c5a9f..e5b9aecc61 100644
--- a/packages/frontend/src/pages/about.vue
+++ b/packages/frontend/src/pages/about.vue
@@ -86,7 +86,7 @@
</template>
<script lang="ts" setup>
-import { ref, computed } from 'vue';
+import { ref, computed, watch } from 'vue';
import XEmojis from './about.emojis.vue';
import XFederation from './about.federation.vue';
import { version, instanceName, host } from '@/config';
@@ -100,6 +100,7 @@ import * as os from '@/os';
import number from '@/filters/number';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
+import { claimAchievement } from '@/scripts/achievements';
const props = withDefaults(defineProps<{
initialTab?: string;
@@ -110,6 +111,12 @@ const props = withDefaults(defineProps<{
let stats = $ref(null);
let tab = $ref(props.initialTab);
+watch($$(tab), () => {
+ if (tab === 'charts') {
+ claimAchievement('viewInstanceChart');
+ }
+});
+
const initStats = () => os.api('stats', {
}).then((res) => {
stats = res;
diff --git a/packages/frontend/src/scripts/achievements.ts b/packages/frontend/src/scripts/achievements.ts
index f511fce3ea..c77f8e12d3 100644
--- a/packages/frontend/src/scripts/achievements.ts
+++ b/packages/frontend/src/scripts/achievements.ts
@@ -58,12 +58,14 @@ export const ACHIEVEMENT_TYPES = [
'collectAchievements30',
'viewAchievements3min',
'iLoveMisskey',
+ 'foundTreasure',
'client30min',
'noteDeletedWithin1min',
'postedAtLateNight',
'postedAt0min0sec',
'selfQuote',
'htl20npm',
+ 'viewInstanceChart',
'outputHelloWorldOnScratchpad',
'open3windows',
'driveFolderCircularReference',
@@ -331,6 +333,11 @@ export const ACHIEVEMENT_BADGES = {
bg: 'linear-gradient(0deg, rgb(255 77 77), rgb(247 155 214))',
frame: 'silver',
},
+ 'foundTreasure': {
+ img: '/fluent-emoji/1f3c6.png',
+ bg: 'linear-gradient(0deg, rgb(197 69 192), rgb(2 112 155))',
+ frame: 'gold',
+ },
'client30min': {
img: '/fluent-emoji/1f552.png',
bg: 'linear-gradient(0deg, rgb(220 223 225), rgb(172 192 207))',
@@ -361,6 +368,11 @@ export const ACHIEVEMENT_BADGES = {
bg: 'linear-gradient(0deg, rgb(220 223 225), rgb(172 192 207))',
frame: 'bronze',
},
+ 'viewInstanceChart': {
+ img: '/fluent-emoji/1f4ca.png',
+ bg: 'linear-gradient(0deg, rgb(58 231 198), rgb(37 194 255))',
+ frame: 'bronze',
+ },
'outputHelloWorldOnScratchpad': {
img: '/fluent-emoji/1f530.png',
bg: 'linear-gradient(0deg, rgb(58 231 198), rgb(37 194 255))',
@@ -437,11 +449,12 @@ export const ACHIEVEMENT_BADGES = {
frame: 'bronze' | 'silver' | 'gold' | 'platinum';
}>;
-export const claimedAchievements = ($i && $i.achievements) ? $i.achievements.map(x => x.name) : [];
+export const claimedAchievements: typeof ACHIEVEMENT_TYPES[number][] = ($i && $i.achievements) ? $i.achievements.map(x => x.name) : [];
const claimingQueue = new Set<string>();
export async function claimAchievement(type: typeof ACHIEVEMENT_TYPES[number]) {
+ if ($i == null) return;
if (claimedAchievements.includes(type)) return;
claimingQueue.add(type);
claimedAchievements.push(type);
diff --git a/packages/frontend/src/scripts/mfm-tags.ts b/packages/frontend/src/scripts/mfm-tags.ts
index be944a7139..a84198282d 100644
--- a/packages/frontend/src/scripts/mfm-tags.ts
+++ b/packages/frontend/src/scripts/mfm-tags.ts
@@ -1 +1 @@
-export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'position', 'fg', 'bg', 'font', 'blur', 'rainbow', 'sparkle', 'rotate'];
+export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'font', 'blur', 'rainbow', 'sparkle', 'rotate'];