+
{{ i18n.ts.localOnly }}
-
-
@{{ user.username }}
-
-
{{ i18n.ts.selectUser }}
-
{{ i18n.ts.remove }}
+
+ {{ i18n.ts.specifyUser }}
+ @{{ user.username }}
+
+
+
@{{ user.username }}
+
+ {{ i18n.ts.selectUser }}
+ {{ i18n.ts.remove }}
+
-
-
+
+
{{ i18n.ts.search }}
@@ -43,6 +47,7 @@ import MkNotes from '@/components/MkNotes.vue';
import MkInput from '@/components/MkInput.vue';
import MkRadios from '@/components/MkRadios.vue';
import MkButton from '@/components/MkButton.vue';
+import MkSwitch from '@/components/MkSwitch.vue';
import { i18n } from '@/i18n';
import * as os from '@/os';
import MkFoldableSection from '@/components/MkFoldableSection.vue';
@@ -59,6 +64,7 @@ let searchQuery = $ref('');
let searchOrigin = $ref('combined');
let notePagination = $ref();
let user = $ref(null);
+let isLocalOnly = $ref(false);
function selectUser() {
os.selectUser().then(_user => {
@@ -98,6 +104,8 @@ async function search() {
},
};
+ if (isLocalOnly) notePagination.params.host = '.';
+
key++;
}
diff --git a/packages/frontend/src/pages/user/flashs.vue b/packages/frontend/src/pages/user/flashs.vue
new file mode 100644
index 0000000000..b91ecb8de6
--- /dev/null
+++ b/packages/frontend/src/pages/user/flashs.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue
index 4763167b18..bce7abf70c 100644
--- a/packages/frontend/src/pages/user/index.vue
+++ b/packages/frontend/src/pages/user/index.vue
@@ -17,6 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
+
@@ -44,6 +45,7 @@ const XReactions = defineAsyncComponent(() => import('./reactions.vue'));
const XClips = defineAsyncComponent(() => import('./clips.vue'));
const XLists = defineAsyncComponent(() => import('./lists.vue'));
const XPages = defineAsyncComponent(() => import('./pages.vue'));
+const XFlashs = defineAsyncComponent(() => import('./flashs.vue'));
const XGallery = defineAsyncComponent(() => import('./gallery.vue'));
const props = withDefaults(defineProps<{
@@ -109,6 +111,10 @@ const headerTabs = $computed(() => user ? [{
key: 'pages',
title: i18n.ts.pages,
icon: 'ti ti-news',
+}, {
+ key: 'flashs',
+ title: 'Play',
+ icon: 'ti ti-player-play',
}, {
key: 'gallery',
title: i18n.ts.gallery,
diff --git a/packages/frontend/src/scripts/aiscript/api.ts b/packages/frontend/src/scripts/aiscript/api.ts
index f69c631198..8dd3b665a5 100644
--- a/packages/frontend/src/scripts/aiscript/api.ts
+++ b/packages/frontend/src/scripts/aiscript/api.ts
@@ -8,6 +8,7 @@ import * as os from '@/os';
import { $i } from '@/account';
import { miLocalStorage } from '@/local-storage';
import { customEmojis } from '@/custom-emojis';
+import { lang } from '@/config';
export function createAiScriptEnv(opts) {
let apiRequests = 0;
@@ -16,6 +17,7 @@ export function createAiScriptEnv(opts) {
USER_NAME: $i ? values.STR($i.name) : values.NULL,
USER_USERNAME: $i ? values.STR($i.username) : values.NULL,
CUSTOM_EMOJIS: utils.jsToVal(customEmojis.value),
+ LOCALE: values.STR(lang),
'Mk:dialog': values.FN_NATIVE(async ([title, text, type]) => {
await os.alert({
type: type ? type.value : 'info',
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index b9c726e134..314358e58a 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -156,7 +156,8 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
icon: 'ti ti-mail',
text: i18n.ts.sendMessage,
action: () => {
- os.post({ specified: user, initialText: `@${user.username} ` });
+ const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${user.host}`;
+ os.post({ specified: user, initialText: `${canonical} ` });
},
}, null, {
icon: 'ti ti-pencil',
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index 1cb3486f74..e9f672384e 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -135,6 +135,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'deviceAccount',
default: false,
},
+ showPreview: {
+ where: 'device',
+ default: false,
+ },
statusbars: {
where: 'deviceAccount',
default: [] as {
diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss
index dbfb8d0dbf..948d27536c 100644
--- a/packages/frontend/src/style.scss
+++ b/packages/frontend/src/style.scss
@@ -527,6 +527,13 @@ hr {
}
}
+._mfm_rainbow_fallback_ {
+ background-image: linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(255, 165, 0) 17%, rgb(255, 255, 0) 33%, rgb(0, 255, 0) 50%, rgb(0, 255, 255) 67%, rgb(0, 0, 255) 83%, rgb(255, 0, 255) 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+}
+
@keyframes mfm-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
diff --git a/packages/frontend/test/url-preview.test.ts b/packages/frontend/test/url-preview.test.ts
index b5fcf9bece..0cf3a417e2 100644
--- a/packages/frontend/test/url-preview.test.ts
+++ b/packages/frontend/test/url-preview.test.ts
@@ -152,4 +152,13 @@ describe('MkUrlPreview', () => {
assert.strictEqual(iframe?.getAttribute('allow'), 'fullscreen;web-share');
assert.strictEqual(iframe?.getAttribute('sandbox'), 'allow-popups allow-scripts allow-same-origin');
});
+
+ test('Loading a post in iframe', async () => {
+ const iframe = await renderAndOpenPreview({
+ url: 'https://x.com/i/web/status/1685072521782325249',
+ });
+ assert.exists(iframe, 'iframe should exist');
+ assert.strictEqual(iframe?.getAttribute('allow'), 'fullscreen;web-share');
+ assert.strictEqual(iframe?.getAttribute('sandbox'), 'allow-popups allow-scripts allow-same-origin');
+ });
});
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index 2dfe6ac0be..e4b7a63c2e 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -2196,6 +2196,10 @@ export type Endpoints = {
req: TODO;
res: TODO;
};
+ 'users/flashs': {
+ req: TODO;
+ res: TODO;
+ };
'users/recommendation': {
req: TODO;
res: TODO;
@@ -2852,7 +2856,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u
//
// src/api.types.ts:16:32 - (ae-forgotten-export) The symbol "TODO" needs to be exported by the entry point index.d.ts
// src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts
-// src/api.types.ts:629:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts
+// src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts
// src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)
diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts
index 5bca981281..ca5b7aea81 100644
--- a/packages/misskey-js/src/api.types.ts
+++ b/packages/misskey-js/src/api.types.ts
@@ -639,6 +639,7 @@ export type Endpoints = {
'users/lists/update': { req: { listId: UserList['id']; name: string; }; res: UserList; };
'users/notes': { req: { userId: User['id']; limit?: number; sinceId?: Note['id']; untilId?: Note['id']; sinceDate?: number; untilDate?: number; }; res: Note[]; };
'users/pages': { req: TODO; res: TODO; };
+ 'users/flashs': { req: TODO; res: TODO; };
'users/recommendation': { req: TODO; res: TODO; };
'users/relation': { req: TODO; res: TODO; };
'users/report-abuse': { req: TODO; res: TODO; };
diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts
index 261ecd33f4..2b144ab4a4 100644
--- a/packages/misskey-js/src/consts.ts
+++ b/packages/misskey-js/src/consts.ts
@@ -39,4 +39,8 @@ export const permissions = [
'write:gallery',
'read:gallery-likes',
'write:gallery-likes',
+ 'read:flash',
+ 'write:flash',
+ 'read:flash-likes',
+ 'write:flash-likes',
];