summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locales/ja-JP.yml6
-rw-r--r--packages/backend/src/core/AchievementService.ts2
-rw-r--r--packages/frontend/src/components/MkPageWindow.vue15
-rw-r--r--packages/frontend/src/os.ts4
-rw-r--r--packages/frontend/src/pages/scratchpad.vue4
-rw-r--r--packages/frontend/src/scripts/achievements.ts12
6 files changed, 41 insertions, 2 deletions
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index e46e6ab9de..aac5d5e833 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1119,6 +1119,12 @@ _achievements:
_htl20npm:
title: "流れるTL"
description: "ホームタイムラインの流速が20npmを越す"
+ _outputHelloWorldOnScratchpad:
+ title: "Hello, world!"
+ description: "スクラッチパッドで hello world を出力した"
+ _open3windows:
+ title: "マルチウィンドウ"
+ description: "ウィンドウを3つ以上開いた状態にした"
_driveFolderCircularReference:
title: "循環参照"
description: "ドライブのフォルダを再帰的な入れ子にしようとした"
diff --git a/packages/backend/src/core/AchievementService.ts b/packages/backend/src/core/AchievementService.ts
index 4ed75308eb..149974452c 100644
--- a/packages/backend/src/core/AchievementService.ts
+++ b/packages/backend/src/core/AchievementService.ts
@@ -65,6 +65,8 @@ const ACHIEVEMENT_TYPES = [
'postedAt0min0sec',
'selfQuote',
'htl20npm',
+ 'outputHelloWorldOnScratchpad',
+ 'open3windows',
'driveFolderCircularReference',
'reactWithoutRead',
'clickedClickHere',
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index 25b9da2d0b..d12aafd06d 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -24,7 +24,7 @@
</template>
<script lang="ts" setup>
-import { ComputedRef, inject, provide } from 'vue';
+import { ComputedRef, inject, onMounted, onUnmounted, provide } from 'vue';
import RouterView from '@/components/global/RouterView.vue';
import MkWindow from '@/components/MkWindow.vue';
import { popout as _popout } from '@/scripts/popout';
@@ -35,6 +35,8 @@ import { mainRouter, routes } from '@/router';
import { Router } from '@/nirax';
import { i18n } from '@/i18n';
import { PageMetadata, provideMetadataReceiver, setPageMetadata } from '@/scripts/page-metadata';
+import { openingWindowsCount } from '@/os';
+import { claimAchievement } from '@/scripts/achievements';
const props = defineProps<{
initialPath: string;
@@ -128,6 +130,17 @@ function popout() {
windowEl.close();
}
+onMounted(() => {
+ openingWindowsCount.value++;
+ if (openingWindowsCount.value >= 3) {
+ claimAchievement('open3windows');
+ }
+});
+
+onUnmounted(() => {
+ openingWindowsCount.value--;
+});
+
defineExpose({
close,
});
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 111bd0cd8d..01f8244060 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -9,7 +9,7 @@ import * as Misskey from 'misskey-js';
import { i18n } from './i18n';
import MkPostFormDialog from '@/components/MkPostFormDialog.vue';
import MkWaitingDialog from '@/components/MkWaitingDialog.vue';
-import MkPageWindow from '@/components/MkPageWindow.vue'
+import MkPageWindow from '@/components/MkPageWindow.vue';
import MkToast from '@/components/MkToast.vue';
import MkDialog from '@/components/MkDialog.vue';
import MkEmojiPickerDialog from '@/components/MkEmojiPickerDialog.vue';
@@ -18,6 +18,8 @@ import MkPopupMenu from '@/components/MkPopupMenu.vue';
import MkContextMenu from '@/components/MkContextMenu.vue';
import { MenuItem } from '@/types/menu';
+export const openingWindowsCount = ref(0);
+
export const apiWithDialog = ((
endpoint: string,
data: Record<string, any> = {},
diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue
index bd68df724e..0d52850b5d 100644
--- a/packages/frontend/src/pages/scratchpad.vue
+++ b/packages/frontend/src/pages/scratchpad.vue
@@ -47,6 +47,7 @@ import { definePageMetadata } from '@/scripts/page-metadata';
import { AsUiComponent, AsUiRoot, patch, registerAsUiLib, render } from '@/scripts/aiscript/ui';
import MkAsUi from '@/components/MkAsUi.vue';
import { miLocalStorage } from '@/local-storage';
+import { claimAchievement } from '@/scripts/achievements';
const parser = new Parser();
let aiscript: Interpreter;
@@ -90,6 +91,9 @@ async function run() {
});
},
out: (value) => {
+ if (value.type === 'str' && value.value.toLowerCase().replace(',', '').includes('hello world')) {
+ claimAchievement('outputHelloWorldOnScratchpad');
+ }
logs.value.push({
id: Math.random(),
text: value.type === 'str' ? value.value : utils.valToString(value),
diff --git a/packages/frontend/src/scripts/achievements.ts b/packages/frontend/src/scripts/achievements.ts
index c8245ad3db..70ea0ffbd4 100644
--- a/packages/frontend/src/scripts/achievements.ts
+++ b/packages/frontend/src/scripts/achievements.ts
@@ -61,6 +61,8 @@ export const ACHIEVEMENT_TYPES = [
'postedAt0min0sec',
'selfQuote',
'htl20npm',
+ 'outputHelloWorldOnScratchpad',
+ 'open3windows',
'driveFolderCircularReference',
'reactWithoutRead',
'clickedClickHere',
@@ -346,6 +348,16 @@ export const ACHIEVEMENT_BADGES = {
bg: 'linear-gradient(0deg, rgb(220 223 225), rgb(172 192 207))',
frame: 'bronze',
},
+ 'outputHelloWorldOnScratchpad': {
+ img: '/fluent-emoji/1f530.png',
+ bg: 'linear-gradient(0deg, rgb(58 231 198), rgb(37 194 255))',
+ frame: 'bronze',
+ },
+ 'open3windows': {
+ img: '/fluent-emoji/1f5a5.png',
+ bg: 'linear-gradient(0deg, rgb(144 224 255), rgb(255 168 252))',
+ frame: 'bronze',
+ },
'driveFolderCircularReference': {
img: '/fluent-emoji/1f4c2.png',
bg: 'linear-gradient(0deg, rgb(144 224 255), rgb(255 168 252))',