Compare commits

...

28 Commits

Author SHA1 Message Date
syuilo
a5df2b0293 Merge branch 'develop' 2023-01-23 20:13:46 +09:00
syuilo
e6eae558d3 13.2.0 2023-01-23 20:13:38 +09:00
syuilo
083fa53d9c update deps 2023-01-23 20:13:18 +09:00
syuilo
7b73dd2d62 enhance(server): onlyServer / onlyQueue オプションを復活 2023-01-23 20:07:48 +09:00
syuilo
7028b7331b 他人の実績閲覧時は獲得条件を表示しないように 2023-01-23 16:40:31 +09:00
syuilo
eefebab530 アニメーション減らすオプション有効時はリアクションのアニメーションを無効に 2023-01-23 16:36:47 +09:00
syuilo
683ddbef3e update contributors 2023-01-23 16:33:47 +09:00
syuilo
bd23522c76 enhance(client): カスタム絵文字一覧のパフォーマンスを改善 2023-01-23 16:19:13 +09:00
nexryai
c1dfbe2623 Hide the value of the object storage secret key input form in the control panel (#9706) 2023-01-23 16:08:09 +09:00
syuilo
ed9facbb33 fix(client): Aiscript: button is not defined
Fix #9704
2023-01-23 12:53:44 +09:00
syuilo
70df8c77fa Merge branch 'develop' 2023-01-22 21:30:06 +09:00
syuilo
2c52655b17 13.1.8 2023-01-22 21:29:57 +09:00
syuilo
6c4c071ae9 New Crowdin updates (#9692)
* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Ukrainian)
2023-01-22 21:28:34 +09:00
tamaina
b19dba80f4 Fix #9691 2023-01-22 12:25:55 +00:00
syuilo
09f4b9e546 Merge branch 'develop' 2023-01-22 21:01:52 +09:00
syuilo
2e6d8c792b 13.1.7 2023-01-22 21:01:42 +09:00
syuilo
e6338a555d mfmにscaleを追加
Resolve #9609
2023-01-22 20:58:52 +09:00
syuilo
313a489ba0 New Crowdin updates (#9689)
* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Ukrainian)
2023-01-22 20:46:43 +09:00
syuilo
b906ff3fed add an achievement 2023-01-22 20:30:56 +09:00
syuilo
ede96eca28 🎨 2023-01-22 20:25:10 +09:00
syuilo
42f3d9188b add a secret achievement 2023-01-22 20:22:38 +09:00
syuilo
a35e0e9261 Merge branch 'develop' 2023-01-22 17:30:12 +09:00
syuilo
80a400a67c 13.1.6 2023-01-22 17:30:04 +09:00
syuilo
7a6534f30b カスタム絵文字のURLが空文字列になる場合があるのを修正 2023-01-22 17:29:31 +09:00
syuilo
68a523ec6d Merge branch 'develop' 2023-01-22 17:19:13 +09:00
syuilo
97d6c1ee86 13.1.5 2023-01-22 17:19:03 +09:00
syuilo
19c93151ce tweak boot.js 2023-01-22 17:18:48 +09:00
syuilo
039a2af3ab tweak boot.js 2023-01-22 17:18:39 +09:00
28 changed files with 408 additions and 134 deletions

View File

@@ -9,6 +9,23 @@
You should also include the user name that made the change.
-->
## 13.2.0 (2021/01/23)
### Improvements
- onlyServer / onlyQueue オプションを復活
- 他人の実績閲覧時は獲得条件を表示しないように
- アニメーション減らすオプション有効時はリアクションのアニメーションを無効に
- カスタム絵文字一覧のパフォーマンスを改善
### Bugfixes
- Aiscript: button is not defined
## 13.1.7 (2023/01/22)
### Improvements
- 新たな実績を追加
- MFMにscaleタグを追加
## 13.1.4 (2023/01/22)
### Improvements

View File

@@ -95,7 +95,7 @@ follow: "Segui"
followRequest: "Richiesta di follow"
followRequests: "Richieste di follow"
unfollow: "Smetti di seguire"
followRequestPending: "La richiesta di follow deve essere approvata"
followRequestPending: "Richiesta in approvazione"
enterEmoji: "Inserisci emoji"
renote: "Rinota"
unrenote: "Annulla rinota"
@@ -1048,6 +1048,9 @@ _achievements:
_noteFavorited1:
title: "Guarda le stelle"
description: "Aggiungi una Nota ai preferiti per la prima volta"
_myNoteFavorited1:
title: "Fornitura stelline"
description: "Qualcuno ha preferito una delle tue Note"
_profileFilled:
title: "Perfettamente"
description: "Imposta il tuo profilo"

View File

@@ -1105,6 +1105,9 @@ _achievements:
title: "I Love Misskey"
description: "\"I ❤ #Misskey\"を投稿した"
flavor: "Misskeyを使ってくださりありがとうございます by 開発チーム"
_foundTreasure:
title: "宝探し"
description: "隠されたお宝を発見した"
_client30min:
title: "ひとやすみ"
description: "クライアントを起動してから30分以上経過した"
@@ -1125,6 +1128,9 @@ _achievements:
_htl20npm:
title: "流れるTL"
description: "ホームタイムラインの流速が20npmを越す"
_viewInstanceChart:
title: "アナリスト"
description: "インスタンスのチャートを表示した"
_outputHelloWorldOnScratchpad:
title: "Hello, world!"
description: "スクラッチパッドで hello world を出力した"

View File

@@ -1048,6 +1048,9 @@ _achievements:
_noteFavorited1:
title: "별을 바라보는 자"
description: "처음으로 노트를 즐겨찾기했습니다"
_myNoteFavorited1:
title: "I wanna Star"
description: "다른 사람이 당신의 노트를 즐겨찾기했습니다"
_profileFilled:
title: "준비 완료"
description: "프로필 설정을 완료했습니다"

View File

@@ -899,6 +899,45 @@ unlike: "Не вподобати"
numberOfLikes: "Вподобання"
show: "Відображення"
color: "Колір"
achievements: "Досягнення"
_achievements:
_types:
_notes1:
title: "налаштовую свій msky"
description: "Перша нотатка"
flavor: "Приємного часу з Misskey!"
_notes10:
title: "Декілька нотаток"
description: "10 нотаток відправлено"
_notes100:
description: "100 нотаток відправлено"
_notes500:
description: "500 нотаток відправлено"
_notes1000:
description: "1 000 нотаток відправлено"
_notes5000:
description: "5 000 нотаток відправлено"
_notes10000:
description: "10 000 нотаток відправлено"
_notes20000:
description: "20 000 нотаток відправлено"
_notes30000:
description: "30 000 нотаток відправлено"
_notes40000:
description: "40 000 нотаток відправлено"
_notes50000:
description: "50 000 нотаток відправлено"
_notes60000:
description: "60 000 нотаток відправлено"
_notes70000:
description: "70 000 нотаток відправлено"
_notes80000:
description: "80 000 нотаток відправлено"
_notes90000:
description: "90 000 нотаток відправлено"
_notes100000:
title: "ALL YOUR NOTE ARE BELONG TO US"
description: "100 000 нотаток відправлено"
_role:
priority: "Пріоритет"
_priority:

View File

@@ -956,7 +956,7 @@ _achievements:
title: "满是帖子"
description: "发布了500篇帖子"
_notes1000:
title: "帖成山"
title: "帖成山"
description: "发布了1,000篇帖子"
_notes5000:
title: "帖如泉涌"

View File

@@ -1047,25 +1047,59 @@ _achievements:
description: "第一次將貼文收進摘錄"
_noteFavorited1:
title: "觀星者"
description: "第一次將貼文收我的最愛"
description: "第一次將貼文收藏至我的最愛"
_myNoteFavorited1:
title: "想要星星"
description: "自己的貼文被他人收藏至「我的最愛」了"
_profileFilled:
title: "有備而來"
description: "設定了個人檔案"
_markedAsCat:
title: "我是貓"
description: "已將帳戶設定為貓"
flavor: "還沒有名字。"
_following1:
title: "首次追隨"
description: "首次追隨了"
_following10:
title: "跟著跟著"
description: "跟隨超過10人了"
_following50:
title: "朋友很多"
description: "跟隨超過50人了"
_following100:
title: "100位朋友"
description: "跟隨超過100人了"
_following300:
title: "朋友過多"
description: "跟隨超過300人了"
_followers1:
title: "第一個追隨者"
description: "第一次被追隨"
_followers10:
title: "Follow me!"
description: "跟隨者超過10人了"
_followers50:
title: "成群結隊"
description: "跟隨者超過50人了"
_followers100:
title: "紅人"
description: "跟隨者超過100人了"
_followers300:
title: "請排成一排"
description: "跟隨者超過300人了"
_followers500:
title: "基站"
description: "超過500名追隨者"
description: "超過500名追隨者"
_followers1000:
title: "影響者"
description: "超過1000名追隨者"
description: "超過1000名追隨者"
_collectAchievements30:
title: "成就收藏家"
description: "獲得30個以上的成就"
_viewAchievements3min:
title: "喜愛成就"
description: "看成就列表要花3分鐘以上"
description: "看成就列表要花3分鐘以上"
_iLoveMisskey:
title: "I Love Misskey"
description: "發布「I ❤ #Misskey」"
@@ -1083,6 +1117,7 @@ _achievements:
_postedAt0min0sec:
title: "報時"
description: "在0分0秒發佈貼文"
flavor: "啵.啵.啵.嗶ー"
_selfQuote:
title: "自我引用"
description: "引用了自己的貼文"
@@ -1094,7 +1129,7 @@ _achievements:
description: "在暫存記憶體輸出了 hello world"
_open3windows:
title: "多重視窗"
description: "開啟3個以上的視窗"
description: "開啟3個以上的視窗"
_driveFolderCircularReference:
title: "循環引用"
description: "試圖遞迴套入雲端硬碟資料夾"
@@ -1110,6 +1145,30 @@ _achievements:
_setNameToSyuilo:
title: "神的情結"
description: "將名稱設定為 syuilo"
_passedSinceAccountCreated1:
title: "一周年"
description: "自建立帳戶開始過了1年"
_passedSinceAccountCreated2:
title: "二周年"
description: "自建立帳戶開始過了2年"
_passedSinceAccountCreated3:
title: "三周年"
description: "自建立帳戶開始過了3年"
_loggedInOnBirthday:
title: "生日快樂"
description: "在生日當天登入了"
_loggedInOnNewYearsDay:
title: "新年快樂"
description: "在元旦當天登入了"
flavor: "今年也請對敝實例多多指教"
_cookieClicked:
title: "點擊餅乾的遊戲"
description: "點擊了餅乾"
flavor: "是不是軟體有問題?"
_brainDiver:
title: "Brain Driver"
description: "發佈了Brain Driver的連結"
flavor: "Misskey-Misskey La-Tu-Ma"
_role:
new: "建立角色"
edit: "編輯角色"
@@ -1759,6 +1818,7 @@ _notification:
pollEnded: "問卷調查已產生結果"
unreadAntennaNote: "天線 {name}"
emptyPushNotificationMessage: "推送通知已更新"
achievementEarned: "獲得成就"
_types:
all: "全部 "
follow: "追隨中"

View File

@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "13.1.4",
"version": "13.2.0",
"codename": "nasubi",
"repository": {
"type": "git",

View File

@@ -23,9 +23,9 @@
"@tensorflow/tfjs-node": "4.1.0"
},
"dependencies": {
"@bull-board/api": "^4.10.2",
"@bull-board/fastify": "^4.10.2",
"@bull-board/ui": "^4.10.2",
"@bull-board/api": "^4.11.0",
"@bull-board/fastify": "^4.11.0",
"@bull-board/ui": "^4.11.0",
"@discordapp/twemoji": "14.0.2",
"@fastify/accepts": "4.1.0",
"@fastify/cookie": "^8.3.0",
@@ -120,7 +120,7 @@
"typeorm": "0.3.11",
"typescript": "4.9.4",
"ulid": "2.3.0",
"undici": "^5.15.1",
"undici": "^5.16.0",
"unzipper": "0.10.11",
"uuid": "9.0.0",
"vary": "1.1.2",

View File

@@ -0,0 +1,35 @@
import { NestFactory } from '@nestjs/core';
import { ChartManagementService } from '@/core/chart/ChartManagementService.js';
import { QueueProcessorService } from '@/queue/QueueProcessorService.js';
import { NestLogger } from '@/NestLogger.js';
import { QueueProcessorModule } from '@/queue/QueueProcessorModule.js';
import { JanitorService } from '@/daemons/JanitorService.js';
import { QueueStatsService } from '@/daemons/QueueStatsService.js';
import { ServerStatsService } from '@/daemons/ServerStatsService.js';
import { ServerService } from '@/server/ServerService.js';
import { MainModule } from '@/MainModule.js';
export async function server() {
const app = await NestFactory.createApplicationContext(MainModule, {
logger: new NestLogger(),
});
app.enableShutdownHooks();
const serverService = app.get(ServerService);
serverService.launch();
app.get(ChartManagementService).start();
app.get(JanitorService).start();
app.get(QueueStatsService).start();
app.get(ServerStatsService).start();
}
export async function jobQueue() {
const jobQueue = await NestFactory.createApplicationContext(QueueProcessorModule, {
logger: new NestLogger(),
});
jobQueue.enableShutdownHooks();
jobQueue.get(QueueProcessorService).start();
jobQueue.get(ChartManagementService).start();
}

View File

@@ -6,21 +6,12 @@ import cluster from 'node:cluster';
import chalk from 'chalk';
import chalkTemplate from 'chalk-template';
import semver from 'semver';
import { NestFactory } from '@nestjs/core';
import Logger from '@/logger.js';
import { loadConfig } from '@/config.js';
import type { Config } from '@/config.js';
import { lessThan } from '@/misc/prelude/array.js';
import { showMachineInfo } from '@/misc/show-machine-info.js';
import { DaemonModule } from '@/daemons/DaemonModule.js';
import { JanitorService } from '@/daemons/JanitorService.js';
import { QueueStatsService } from '@/daemons/QueueStatsService.js';
import { ServerStatsService } from '@/daemons/ServerStatsService.js';
import { NestLogger } from '@/NestLogger.js';
import { ChartManagementService } from '@/core/chart/ChartManagementService.js';
import { ServerService } from '@/server/ServerService.js';
import { MainModule } from '@/MainModule.js';
import { envOption } from '../env.js';
import { envOption } from '@/env.js';
import { jobQueue, server } from './common.js';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
@@ -73,14 +64,13 @@ export async function masterMain() {
process.exit(1);
}
const app = await NestFactory.createApplicationContext(MainModule, {
logger: new NestLogger(),
});
app.enableShutdownHooks();
// start server
const serverService = app.get(ServerService);
serverService.launch();
if (envOption.onlyServer) {
await server();
} else if (envOption.onlyQueue) {
await jobQueue();
} else {
await server();
}
bootLogger.succ('Misskey initialized');
@@ -89,11 +79,6 @@ export async function masterMain() {
}
bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, null, true);
app.get(ChartManagementService).start();
app.get(JanitorService).start();
app.get(QueueStatsService).start();
app.get(ServerStatsService).start();
}
function showEnvironment(): void {

View File

@@ -1,23 +1,18 @@
import cluster from 'node:cluster';
import { NestFactory } from '@nestjs/core';
import { ChartManagementService } from '@/core/chart/ChartManagementService.js';
import { QueueProcessorService } from '@/queue/QueueProcessorService.js';
import { NestLogger } from '@/NestLogger.js';
import { QueueProcessorModule } from '@/queue/QueueProcessorModule.js';
import { envOption } from '@/env.js';
import { jobQueue, server } from './common.js';
/**
* Init worker process
*/
export async function workerMain() {
const jobQueue = await NestFactory.createApplicationContext(QueueProcessorModule, {
logger: new NestLogger(),
});
jobQueue.enableShutdownHooks();
// start job queue
jobQueue.get(QueueProcessorService).start();
jobQueue.get(ChartManagementService).start();
if (envOption.onlyServer) {
await server();
} else if (envOption.onlyQueue) {
await jobQueue();
} else {
await jobQueue();
}
if (cluster.isWorker) {
// Send a 'ready' message to parent process

View File

@@ -62,12 +62,14 @@ const ACHIEVEMENT_TYPES = [
'collectAchievements30',
'viewAchievements3min',
'iLoveMisskey',
'foundTreasure',
'client30min',
'noteDeletedWithin1min',
'postedAtLateNight',
'postedAt0min0sec',
'selfQuote',
'htl20npm',
'viewInstanceChart',
'outputHelloWorldOnScratchpad',
'open3windows',
'driveFolderCircularReference',

View File

@@ -32,8 +32,8 @@ export class EmojiEntityService {
name: emoji.name,
category: emoji.category,
host: opts.omitHost ? undefined : emoji.host,
// ?? emoji.originalUrl してるのは後方互換性のため
url: opts.withUrl ? (emoji.publicUrl ?? emoji.originalUrl) : undefined,
// || emoji.originalUrl してるのは後方互換性のためpublicUrlはstringなので??はだめ)
url: opts.withUrl ? (emoji.publicUrl || emoji.originalUrl) : undefined,
};
}

View File

@@ -55,7 +55,7 @@
renderError('META_FETCH');
return;
}
const meta = await res.json();
const meta = await metaRes.json();
const v = meta.version;
if (v == null) {
renderError('META_FETCH_V');

View File

@@ -16,8 +16,8 @@
<time v-tooltip="new Date(achievement.unlockedAt).toLocaleString()">{{ new Date(achievement.unlockedAt).getFullYear() }}/{{ new Date(achievement.unlockedAt).getMonth() + 1 }}/{{ new Date(achievement.unlockedAt).getDate() }}</time>
</span>
</div>
<div :class="$style.description">{{ i18n.ts._achievements._types['_' + achievement.name].description }}</div>
<div v-if="i18n.ts._achievements._types['_' + achievement.name].flavor" :class="$style.flavor">{{ i18n.ts._achievements._types['_' + achievement.name].flavor }}</div>
<div :class="$style.description">{{ withDescription ? i18n.ts._achievements._types['_' + achievement.name].description : '???' }}</div>
<div v-if="i18n.ts._achievements._types['_' + achievement.name].flavor && withDescription" :class="$style.flavor">{{ i18n.ts._achievements._types['_' + achievement.name].flavor }}</div>
</div>
</div>
<template v-if="withLocked">
@@ -49,8 +49,10 @@ import { ACHIEVEMENT_TYPES, ACHIEVEMENT_BADGES, claimAchievement } from '@/scrip
const props = withDefaults(defineProps<{
user: misskey.entities.User;
withLocked: boolean;
withDescription: boolean;
}>(), {
withLocked: true,
withDescription: true,
});
let achievements = $ref();

View File

@@ -21,6 +21,7 @@ import { useTooltip } from '@/scripts/use-tooltip';
import { $i } from '@/account';
import MkReactionEffect from '@/components/MkReactionEffect.vue';
import { claimAchievement } from '@/scripts/achievements';
import { defaultStore } from '@/store';
const props = defineProps<{
reaction: string;
@@ -61,6 +62,7 @@ const toggleReaction = () => {
const anime = () => {
if (document.hidden) return;
if (!defaultStore.state.animation) return;
const rect = buttonEl.value.getBoundingClientRect();
const x = rect.left + 16;

View File

@@ -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';

View File

@@ -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>
@@ -37,11 +40,31 @@
</FormSection>
<FormSection>
<template #label>{{ i18n.ts._aboutMisskey.contributors }}</template>
<div class="_formLinksGrid">
<FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
<FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
<FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
<div :class="$style.contributors">
<a href="https://github.com/syuilo" target="_blank" :class="$style.contributor">
<img src="https://avatars.githubusercontent.com/u/4439005?v=4" :class="$style.contributorAvatar">
<span :class="$style.contributorUsername">@syuilo</span>
</a>
<a href="https://github.com/tamaina" target="_blank" :class="$style.contributor">
<img src="https://avatars.githubusercontent.com/u/7973572?v=4" :class="$style.contributorAvatar">
<span :class="$style.contributorUsername">@tamaina</span>
</a>
<a href="https://github.com/acid-chicken" target="_blank" :class="$style.contributor">
<img src="https://avatars.githubusercontent.com/u/20679825?v=4" :class="$style.contributorAvatar">
<span :class="$style.contributorUsername">@acid-chicken</span>
</a>
<a href="https://github.com/rinsuki" target="_blank" :class="$style.contributor">
<img src="https://avatars.githubusercontent.com/u/6533808?v=4" :class="$style.contributorAvatar">
<span :class="$style.contributorUsername">@rinsuki</span>
</a>
<a href="https://github.com/mei23" target="_blank" :class="$style.contributor">
<img src="https://avatars.githubusercontent.com/u/30769358?v=4" :class="$style.contributorAvatar">
<span :class="$style.contributorUsername">@mei23</span>
</a>
<a href="https://github.com/robflop" target="_blank" :class="$style.contributor">
<img src="https://avatars.githubusercontent.com/u/8159402?v=4" :class="$style.contributorAvatar">
<span :class="$style.contributorUsername">@robflop</span>
</a>
</div>
<template #caption><MkLink url="https://github.com/misskey-dev/misskey/graphs/contributors">{{ i18n.ts._aboutMisskey.allContributors }}</MkLink></template>
</FormSection>
@@ -70,6 +93,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 +177,8 @@ const patrons = [
'pixeldesu',
];
let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
let easterEggReady = false;
let easterEggEmojis = $ref([]);
let easterEggEngine = $ref(null);
@@ -187,6 +214,11 @@ function iLoveMisskey() {
});
}
function getTreasure() {
thereIsTreasure = false;
claimAchievement('foundTreasure');
}
onBeforeUnmount(() => {
if (easterEggEngine) {
easterEggEngine.stop();
@@ -207,54 +239,114 @@ definePageMetadata({
.znqjceqz {
> .about {
position: relative;
text-align: center;
padding: 16px;
border-radius: var(--radius);
&.playing {
&, * {
user-select: none;
}
* {
will-change: transform;
}
> .emoji {
visibility: visible;
}
}
> .icon {
display: block;
width: 80px;
margin: 0 auto;
border-radius: 16px;
}
> .misskey {
margin: 0.75em auto 0 auto;
width: max-content;
}
> .version {
margin: 0 auto;
width: max-content;
opacity: 0.5;
}
> .emoji {
> .treasure {
position: absolute;
top: 0;
top: 60px;
left: 0;
visibility: hidden;
right: 0;
margin: 0 auto;
width: min-content;
> .treasureImg {
width: 25px;
vertical-align: bottom;
}
}
> .container {
position: relative;
text-align: center;
padding: 16px;
&.playing {
&, * {
user-select: none;
}
* {
will-change: transform;
}
> .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;
}
}
}
}
}
</style>
<style lang="scss" module>
.contributors {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-gap: 12px;
}
.contributor {
display: flex;
align-items: center;
padding: 12px;
background: var(--buttonBg);
border-radius: 6px;
&:hover {
text-decoration: none;
background: var(--buttonHoverBg);
}
&.active {
color: var(--accent);
background: var(--buttonHoverBg);
}
}
.contributorAvatar {
width: 30px;
border-radius: 100%;
}
.contributorUsername {
margin-left: 12px;
}
</style>

View File

@@ -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;

View File

@@ -38,7 +38,7 @@
<template #label>Access key</template>
</MkInput>
<MkInput v-model="objectStorageSecretKey">
<MkInput v-model="objectStorageSecretKey" type="password">
<template #prefix><i class="ti ti-key"></i></template>
<template #label>Secret key</template>
</MkInput>

View File

@@ -1,6 +1,6 @@
<template>
<button class="zuvgdzyu _button" @click="menu">
<img :src="`/emoji/${emoji.name}.webp`" class="img" loading="lazy"/>
<img :src="emoji.url" class="img" loading="lazy"/>
<div class="body">
<div class="name _monospace">{{ emoji.name }}</div>
<div class="info">{{ emoji.aliases.join(' ') }}</div>
@@ -15,7 +15,12 @@ import copyToClipboard from '@/scripts/copy-to-clipboard';
import { i18n } from '@/i18n';
const props = defineProps<{
emoji: Record<string, unknown>; // TODO
emoji: {
name: string;
aliases: string[];
category: string;
url: string;
};
}>();
function menu(ev) {

View File

@@ -1,6 +1,6 @@
<template>
<MkSpacer :content-max="1200">
<MkAchievements :user="user" :with-locked="false"/>
<MkAchievements :user="user" :with-locked="false" :with-description="$i != null && (props.user.id === $i.id)"/>
</MkSpacer>
</template>

View File

@@ -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);

View File

@@ -303,7 +303,7 @@ function getButtonOptions(def: values.Value | undefined, call: (fn: values.VFn,
if (primary) utils.assertBoolean(primary);
const rounded = def.value.get('rounded');
if (rounded) utils.assertBoolean(rounded);
const disabled = button.value.get('disabled');
const disabled = def.value.get('disabled');
if (disabled) utils.assertBoolean(disabled);
return {

View File

@@ -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'];

View File

@@ -54,6 +54,8 @@ export default defineConfig(({ command, mode }) => {
'@/': __dirname + '/src/',
'/client-assets/': __dirname + '/assets/',
'/static-assets/': __dirname + '/../backend/assets/',
'/fluent-emojis/': __dirname + '/../../fluent-emojis/dist/',
'/fluent-emoji/': __dirname + '/../../fluent-emojis/dist/',
},
},

42
pnpm-lock.yaml generated
View File

@@ -48,9 +48,9 @@ importers:
packages/backend:
specifiers:
'@bull-board/api': ^4.10.2
'@bull-board/fastify': ^4.10.2
'@bull-board/ui': ^4.10.2
'@bull-board/api': ^4.11.0
'@bull-board/fastify': ^4.11.0
'@bull-board/ui': ^4.11.0
'@discordapp/twemoji': 14.0.2
'@fastify/accepts': 4.1.0
'@fastify/cookie': ^8.3.0
@@ -202,7 +202,7 @@ importers:
typeorm: 0.3.11
typescript: 4.9.4
ulid: 2.3.0
undici: ^5.15.1
undici: ^5.16.0
unzipper: 0.10.11
uuid: 9.0.0
vary: 1.1.2
@@ -211,9 +211,9 @@ importers:
ws: 8.12.0
xev: 3.0.2
dependencies:
'@bull-board/api': 4.10.2
'@bull-board/fastify': 4.10.2
'@bull-board/ui': 4.10.2
'@bull-board/api': 4.11.0
'@bull-board/fastify': 4.11.0
'@bull-board/ui': 4.11.0
'@discordapp/twemoji': 14.0.2
'@fastify/accepts': 4.1.0
'@fastify/cookie': 8.3.0
@@ -308,7 +308,7 @@ importers:
typeorm: 0.3.11_ioredis@4.28.5+pg@8.8.0
typescript: 4.9.4
ulid: 2.3.0
undici: 5.15.1
undici: 5.16.0
unzipper: 0.10.11
uuid: 9.0.0
vary: 1.1.2
@@ -915,17 +915,17 @@ packages:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
dev: true
/@bull-board/api/4.10.2:
resolution: {integrity: sha512-lRHo0A7hsz71aOx1ZN0SmLLWfSuvKdL6EZ4imlgo5SuXGozybvlRc5KPIJU2/E1w5meoUGi+nFezBwp1gT/SMw==}
/@bull-board/api/4.11.0:
resolution: {integrity: sha512-qFnG63s3BkaslsNnXYagEUcdeK9SijZTJ+I4vMU+OiZt9VlKh01X1KjNlqjF9guvWcjk+Rg8UOMm0fWwM6PK6g==}
dependencies:
redis-info: 3.1.0
dev: false
/@bull-board/fastify/4.10.2:
resolution: {integrity: sha512-yp/TlfyfMBgR6vibyCUBOTKn2BFlBSLxkJxzlvIcMDs2Vl3PMXMs4YoCr2o3m+dXxSNzpTfomxAc5XQfJdp0VQ==}
/@bull-board/fastify/4.11.0:
resolution: {integrity: sha512-G4sAFVx5kGT5T/F2gL91RjZ2+YrMHNrLWoVo/QfHMcZe3RoOP4PpbOLgLC/O67KYn3JK6t8ysGyyP035OSJ2HA==}
dependencies:
'@bull-board/api': 4.10.2
'@bull-board/ui': 4.10.2
'@bull-board/api': 4.11.0
'@bull-board/ui': 4.11.0
'@fastify/static': 6.6.1
'@fastify/view': 7.4.0
ejs: 3.1.8
@@ -933,10 +933,10 @@ packages:
- supports-color
dev: false
/@bull-board/ui/4.10.2:
resolution: {integrity: sha512-vaHGojG5D3xjnaed3nwOaLy4Y06RgDJdYRaFR5E06SjZ0vOvjVYGD6s4cykK512Aw/ElFhKDPwzhf8BvpwAtDQ==}
/@bull-board/ui/4.11.0:
resolution: {integrity: sha512-/Yb7x/3tWxysA2jRDQ89xEPnscvfGQdf4MmDRzWH5lDkVmL8b1HvZAQxLrHcxwB6y16oorQTf/1KbRZl0rJDHg==}
dependencies:
'@bull-board/api': 4.10.2
'@bull-board/api': 4.11.0
dev: false
/@chainsafe/is-ip/2.0.1:
@@ -1077,7 +1077,7 @@ packages:
dependencies:
ky: 0.30.0
ky-universal: 0.10.1_ky@0.30.0
undici: 5.15.1
undici: 5.16.0
transitivePeerDependencies:
- web-streams-polyfill
dev: false
@@ -1402,7 +1402,7 @@ packages:
fastify-plugin: 4.5.0
pump: 3.0.0
tiny-lru: 10.0.1
undici: 5.15.1
undici: 5.16.0
dev: false
/@fastify/send/1.0.0:
@@ -13541,8 +13541,8 @@ packages:
undertaker-registry: 1.0.1
dev: false
/undici/5.15.1:
resolution: {integrity: sha512-XLk8g0WAngdvFqTI+VKfBtM4YWXgdxkf1WezC771Es0Dd+Pm1KmNx8t93WTC+Hh9tnghmVxkclU1HN+j+CvIUA==}
/undici/5.16.0:
resolution: {integrity: sha512-KWBOXNv6VX+oJQhchXieUznEmnJMqgXMbs0xxH2t8q/FUAWSJvOSr/rMaZKnX5RIVq7JDn0JbP4BOnKG2SGXLQ==}
engines: {node: '>=12.18'}
dependencies:
busboy: 1.6.0