-
+
{{ i18n.ts.loadMore }}
-
+
{{ i18n.ts.loadMore }}
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 1a49cd1dd..462473306 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -431,6 +431,10 @@ function pushVisibleUser(user) {
function addVisibleUser() {
os.selectUser().then(user => {
pushVisibleUser(user);
+
+ if (!text.toLowerCase().includes(`@${user.username.toLowerCase()}`)) {
+ text = `@${Acct.toString(user)} ${text}`;
+ }
});
}
@@ -667,7 +671,14 @@ async function post(ev?: MouseEvent) {
if ((text.includes('love') || text.includes('❤')) && text.includes('misskey')) {
claimAchievement('iLoveMisskey');
}
- if (text.includes('Efrlqw8ytg4'.toLowerCase()) || text.includes('XVCwzwxdHuA'.toLowerCase())) {
+ if (
+ text.includes('https://youtu.be/Efrlqw8ytg4'.toLowerCase()) ||
+ text.includes('https://www.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
+ text.includes('https://m.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
+ text.includes('https://youtu.be/XVCwzwxdHuA'.toLowerCase()) ||
+ text.includes('https://www.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase()) ||
+ text.includes('https://m.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase())
+ ) {
claimAchievement('brainDiver');
}
diff --git a/packages/frontend/src/components/MkSignup.vue b/packages/frontend/src/components/MkSignup.vue
index 7778e8f50..bd1ac79dd 100644
--- a/packages/frontend/src/components/MkSignup.vue
+++ b/packages/frontend/src/components/MkSignup.vue
@@ -10,6 +10,7 @@
@
@{{ host }}
+ {{ i18n.ts.cannotBeChangedLater }}
{{ i18n.ts.checking }}
{{ i18n.ts.available }}
{{ i18n.ts.unavailable }}
@@ -117,7 +118,9 @@ const shouldDisableSubmitting = $computed((): boolean => {
instance.enableHcaptcha && !hCaptchaResponse ||
instance.enableRecaptcha && !reCaptchaResponse ||
instance.enableTurnstile && !turnstileResponse ||
- passwordRetypeState === 'not-match';
+ instance.emailRequiredForSignup && emailState !== 'ok' ||
+ usernameState !== 'ok' ||
+ passwordRetypeState !== 'match';
});
function onChangeUsername(): void {
diff --git a/packages/frontend/src/components/form/section.vue b/packages/frontend/src/components/form/section.vue
index a83816497..55308b9c8 100644
--- a/packages/frontend/src/components/form/section.vue
+++ b/packages/frontend/src/components/form/section.vue
@@ -1,7 +1,7 @@
-
-
-
+
@@ -13,31 +13,31 @@ defineProps<{
}>();
-
diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index bd72ee466..3037d7100 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -84,6 +84,12 @@
{{ i18n.ts._aboutMisskey.morePatrons }}
+
+ Special thanks
+
+

+
+
@@ -120,6 +126,9 @@ const patronsWithIcon = [{
}, {
name: 'ぱーこ',
icon: 'https://misskey-hub.net/patrons/79c6602ffade489e8df2fcf2c2bc5d9d.jpg',
+}, {
+ name: 'わっほー☆',
+ icon: 'https://misskey-hub.net/patrons/d31d5d13924443a082f3da7966318a0a.jpg',
}];
const patrons = [
@@ -203,6 +212,8 @@ const patrons = [
'pixeldesu',
'あめ玉',
'氷月氷華里',
+ 'Ebise Lutica',
+ '巣黒るい@リスケモ男の娘VTuber!',
];
let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
diff --git a/packages/frontend/src/pages/admin/roles.edit.vue b/packages/frontend/src/pages/admin/roles.edit.vue
index 2a65a7518..ac6cca84c 100644
--- a/packages/frontend/src/pages/admin/roles.edit.vue
+++ b/packages/frontend/src/pages/admin/roles.edit.vue
@@ -46,7 +46,8 @@ if (props.id) {
data = {
name: 'New Role',
description: '',
- rolePermission: 'normal',
+ isAdministrator: false,
+ isModerator: false,
color: null,
iconUrl: null,
target: 'manual',
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue
index 001e3e4e4..56bbd0e0a 100644
--- a/packages/frontend/src/pages/channel.vue
+++ b/packages/frontend/src/pages/channel.vue
@@ -85,7 +85,7 @@ function edit() {
function openPostForm() {
os.post({
channel: {
- id: channel.channelId,
+ id: channel.id,
},
});
}
diff --git a/packages/frontend/src/pages/explore.roles.vue b/packages/frontend/src/pages/explore.roles.vue
index 8be11008c..51177d079 100644
--- a/packages/frontend/src/pages/explore.roles.vue
+++ b/packages/frontend/src/pages/explore.roles.vue
@@ -16,7 +16,7 @@ let roles = $ref();
os.api('roles/list', {
limit: 30,
}).then(res => {
- roles = res;
+ roles = res.filter(x => x.target === 'manual');
});
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue
index 8c8c9b9db..2e2c456c0 100644
--- a/packages/frontend/src/pages/settings/general.vue
+++ b/packages/frontend/src/pages/settings/general.vue
@@ -193,6 +193,7 @@ watch([
enableInfiniteScroll,
squareAvatars,
aiChanMode,
+ showNoteActionsOnlyHover,
showGapBetweenNotesInTimeline,
instanceTicker,
overridedDeviceKind,
diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue
index a08308f0c..577337868 100644
--- a/packages/frontend/src/pages/settings/mute-block.vue
+++ b/packages/frontend/src/pages/settings/mute-block.vue
@@ -5,22 +5,60 @@
-
- {{ i18n.ts.noUsers }}
-
-
-
-
+
+
+
+

+
{{ i18n.ts.noUsers }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Muted at:
+
Period: {{ item.expiresAt.toLocaleString() }}
+
Period: {{ i18n.ts.indefinitely }}
+
+
+
-
- {{ i18n.ts.noUsers }}
-
-
-
-
+
+
+
+

+
{{ i18n.ts.noUsers }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Blocked at:
+
Period: {{ item.expiresAt.toLocaleString() }}
+
Period: {{ i18n.ts.indefinitely }}
+
+
+
@@ -36,6 +74,8 @@ import FormLink from '@/components/form/link.vue';
import { userPage } from '@/filters/user';
import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
+import MkUserCardMini from '@/components/MkUserCardMini.vue';
+import * as os from '@/os';
let tab = $ref('mute');
@@ -49,6 +89,47 @@ const blockingPagination = {
limit: 10,
};
+let expandedMuteItems = $ref([]);
+let expandedBlockItems = $ref([]);
+
+async function unmute(user, ev) {
+ os.popupMenu([{
+ text: i18n.ts.unmute,
+ icon: 'ti ti-x',
+ action: async () => {
+ await os.apiWithDialog('mute/delete', { userId: user.id });
+ //role.users = role.users.filter(u => u.id !== user.id);
+ },
+ }], ev.currentTarget ?? ev.target);
+}
+
+async function unblock(user, ev) {
+ os.popupMenu([{
+ text: i18n.ts.unblock,
+ icon: 'ti ti-x',
+ action: async () => {
+ await os.apiWithDialog('blocking/delete', { userId: user.id });
+ //role.users = role.users.filter(u => u.id !== user.id);
+ },
+ }], ev.currentTarget ?? ev.target);
+}
+
+async function toggleMuteItem(item) {
+ if (expandedMuteItems.includes(item.id)) {
+ expandedMuteItems = expandedMuteItems.filter(x => x !== item.id);
+ } else {
+ expandedMuteItems.push(item.id);
+ }
+}
+
+async function toggleBlockItem(item) {
+ if (expandedBlockItems.includes(item.id)) {
+ expandedBlockItems = expandedBlockItems.filter(x => x !== item.id);
+ } else {
+ expandedBlockItems.push(item.id);
+ }
+}
+
const headerActions = $computed(() => []);
const headerTabs = $computed(() => []);
@@ -58,3 +139,43 @@ definePageMetadata({
icon: 'ti ti-ban',
});
+
+
diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue
index 5e7895912..0cc9912e4 100644
--- a/packages/frontend/src/pages/user/home.vue
+++ b/packages/frontend/src/pages/user/home.vue
@@ -355,6 +355,9 @@ onUnmounted(() => {
> .roles {
padding: 24px 24px 0 154px;
font-size: 0.95em;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
> .role {
border: solid 1px var(--color, var(--divider));
@@ -496,7 +499,7 @@ onUnmounted(() => {
> .roles {
padding: 16px 16px 0 16px;
- text-align: center;
+ justify-content: center;
}
> .description {
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index 5170ca4c8..f5aa551bd 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -111,7 +111,7 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
icon: 'ti ti-mail',
text: i18n.ts.sendMessage,
action: () => {
- os.post({ specified: user });
+ os.post({ specified: user, initialText: `@${user.username} ` });
},
}, null, {
type: 'parent',
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index a5959a7cd..f5b20ebe6 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -332,8 +332,8 @@ export class ColdDeviceStorage {
plugins: [] as Plugin[],
mediaVolume: 0.5,
sound_masterVolume: 0.5,
- sound_note: { type: 'syuilo/n-aec', volume: 0.5 },
- sound_noteMy: { type: 'syuilo/n-cea', volume: 0.5 },
+ sound_note: { type: 'syuilo/n-eca', volume: 0.5 },
+ sound_noteMy: { type: 'syuilo/n-cea-4va', volume: 0.5 },
sound_notification: { type: 'syuilo/n-ea', volume: 0.5 },
sound_chat: { type: 'syuilo/pope1', volume: 0.5 },
sound_chatBg: { type: 'syuilo/waon', volume: 0.5 },
diff --git a/scripts/dev.js b/scripts/dev.js
index b1970ebc5..db7bc11fe 100644
--- a/scripts/dev.js
+++ b/scripts/dev.js
@@ -40,8 +40,9 @@ const fs = require('fs');
const start = async () => {
try {
- const exist = fs.existsSync(__dirname + '/../packages/backend/built/boot/index.js')
- if (!exist) throw new Error('not exist yet');
+ const stat = fs.statSync(__dirname + '/../packages/backend/built/boot/index.js');
+ if (!stat) throw new Error('not exist yet');
+ if (stat.size === 0) throw new Error('not built yet');
await execa('pnpm', ['start'], {
cwd: __dirname + '/../',