Merge branch 'develop' into feature/channel_muting
This commit is contained in:
commit
012e3fec51
|
@ -15,16 +15,16 @@
|
||||||
- Fix: テーマプレビューが見れない問題を修正
|
- Fix: テーマプレビューが見れない問題を修正
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正
|
|
||||||
- Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949)
|
- Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949)
|
||||||
- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006)
|
|
||||||
- Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036)
|
|
||||||
- Enhance: エンドポイント`clips/update`の必須項目を`clipId`のみに
|
- Enhance: エンドポイント`clips/update`の必須項目を`clipId`のみに
|
||||||
- Enhance: エンドポイント`admin/roles/update`の必須項目を`roleId`のみに
|
- Enhance: エンドポイント`admin/roles/update`の必須項目を`roleId`のみに
|
||||||
- Enhance: エンドポイント`pages/update`の必須項目を`pageId`のみに
|
- Enhance: エンドポイント`pages/update`の必須項目を`pageId`のみに
|
||||||
- Enhance: エンドポイント`gallery/posts/update`の必須項目を`postId`のみに
|
- Enhance: エンドポイント`gallery/posts/update`の必須項目を`postId`のみに
|
||||||
- Enhance: エンドポイント`i/webhook/update`の必須項目を`webhookId`のみに
|
- Enhance: エンドポイント`i/webhook/update`の必須項目を`webhookId`のみに
|
||||||
- Enhance: エンドポイント`admin/ad/update`の必須項目を`id`のみに
|
- Enhance: エンドポイント`admin/ad/update`の必須項目を`id`のみに
|
||||||
|
- Fix: チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正
|
||||||
|
- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006)
|
||||||
|
- Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036)
|
||||||
- Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059)
|
- Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059)
|
||||||
- Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正
|
- Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正
|
||||||
- Fix: 自分以外のクリップ内のノート個数が見えることがあるのを修正
|
- Fix: 自分以外のクリップ内のノート個数が見えることがあるのを修正
|
||||||
|
|
|
@ -13,10 +13,12 @@ import { intersperse } from '@/misc/prelude/array.js';
|
||||||
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
|
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
|
||||||
import type { IMentionedRemoteUsers } from '@/models/Note.js';
|
import type { IMentionedRemoteUsers } from '@/models/Note.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import * as TreeAdapter from '../../node_modules/parse5/dist/tree-adapters/default.js';
|
import type { DefaultTreeAdapterMap } from 'parse5';
|
||||||
import type * as mfm from 'mfm-js';
|
import type * as mfm from 'mfm-js';
|
||||||
|
|
||||||
const treeAdapter = TreeAdapter.defaultTreeAdapter;
|
const treeAdapter = parse5.defaultTreeAdapter;
|
||||||
|
type Node = DefaultTreeAdapterMap['node'];
|
||||||
|
type ChildNode = DefaultTreeAdapterMap['childNode'];
|
||||||
|
|
||||||
const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
|
const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
|
||||||
const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/;
|
const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/;
|
||||||
|
@ -46,7 +48,7 @@ export class MfmService {
|
||||||
|
|
||||||
return text.trim();
|
return text.trim();
|
||||||
|
|
||||||
function getText(node: TreeAdapter.Node): string {
|
function getText(node: Node): string {
|
||||||
if (treeAdapter.isTextNode(node)) return node.value;
|
if (treeAdapter.isTextNode(node)) return node.value;
|
||||||
if (!treeAdapter.isElementNode(node)) return '';
|
if (!treeAdapter.isElementNode(node)) return '';
|
||||||
if (node.nodeName === 'br') return '\n';
|
if (node.nodeName === 'br') return '\n';
|
||||||
|
@ -58,7 +60,7 @@ export class MfmService {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function appendChildren(childNodes: TreeAdapter.ChildNode[]): void {
|
function appendChildren(childNodes: ChildNode[]): void {
|
||||||
if (childNodes) {
|
if (childNodes) {
|
||||||
for (const n of childNodes) {
|
for (const n of childNodes) {
|
||||||
analyze(n);
|
analyze(n);
|
||||||
|
@ -66,14 +68,16 @@ export class MfmService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function analyze(node: TreeAdapter.Node) {
|
function analyze(node: Node) {
|
||||||
if (treeAdapter.isTextNode(node)) {
|
if (treeAdapter.isTextNode(node)) {
|
||||||
text += node.value;
|
text += node.value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip comment or document type node
|
// Skip comment or document type node
|
||||||
if (!treeAdapter.isElementNode(node)) return;
|
if (!treeAdapter.isElementNode(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (node.nodeName) {
|
switch (node.nodeName) {
|
||||||
case 'br': {
|
case 'br': {
|
||||||
|
@ -81,8 +85,7 @@ export class MfmService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'a':
|
case 'a': {
|
||||||
{
|
|
||||||
const txt = getText(node);
|
const txt = getText(node);
|
||||||
const rel = node.attrs.find(x => x.name === 'rel');
|
const rel = node.attrs.find(x => x.name === 'rel');
|
||||||
const href = node.attrs.find(x => x.name === 'href');
|
const href = node.attrs.find(x => x.name === 'href');
|
||||||
|
@ -90,7 +93,7 @@ export class MfmService {
|
||||||
// ハッシュタグ
|
// ハッシュタグ
|
||||||
if (normalizedHashtagNames && href && normalizedHashtagNames.has(normalizeForSearch(txt))) {
|
if (normalizedHashtagNames && href && normalizedHashtagNames.has(normalizeForSearch(txt))) {
|
||||||
text += txt;
|
text += txt;
|
||||||
// メンション
|
// メンション
|
||||||
} else if (txt.startsWith('@') && !(rel && rel.value.startsWith('me '))) {
|
} else if (txt.startsWith('@') && !(rel && rel.value.startsWith('me '))) {
|
||||||
const part = txt.split('@');
|
const part = txt.split('@');
|
||||||
|
|
||||||
|
@ -102,7 +105,7 @@ export class MfmService {
|
||||||
} else if (part.length === 3) {
|
} else if (part.length === 3) {
|
||||||
text += txt;
|
text += txt;
|
||||||
}
|
}
|
||||||
// その他
|
// その他
|
||||||
} else {
|
} else {
|
||||||
const generateLink = () => {
|
const generateLink = () => {
|
||||||
if (!href && !txt) {
|
if (!href && !txt) {
|
||||||
|
@ -130,8 +133,7 @@ export class MfmService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'h1':
|
case 'h1': {
|
||||||
{
|
|
||||||
text += '【';
|
text += '【';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
text += '】\n';
|
text += '】\n';
|
||||||
|
@ -139,16 +141,14 @@ export class MfmService {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'strong':
|
case 'strong': {
|
||||||
{
|
|
||||||
text += '**';
|
text += '**';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
text += '**';
|
text += '**';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'small':
|
case 'small': {
|
||||||
{
|
|
||||||
text += '<small>';
|
text += '<small>';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
text += '</small>';
|
text += '</small>';
|
||||||
|
@ -156,8 +156,7 @@ export class MfmService {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
case 'del':
|
case 'del': {
|
||||||
{
|
|
||||||
text += '~~';
|
text += '~~';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
text += '~~';
|
text += '~~';
|
||||||
|
@ -165,8 +164,7 @@ export class MfmService {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'em':
|
case 'em': {
|
||||||
{
|
|
||||||
text += '<i>';
|
text += '<i>';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
text += '</i>';
|
text += '</i>';
|
||||||
|
@ -207,8 +205,7 @@ export class MfmService {
|
||||||
case 'h3':
|
case 'h3':
|
||||||
case 'h4':
|
case 'h4':
|
||||||
case 'h5':
|
case 'h5':
|
||||||
case 'h6':
|
case 'h6': {
|
||||||
{
|
|
||||||
text += '\n\n';
|
text += '\n\n';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
break;
|
break;
|
||||||
|
@ -221,8 +218,7 @@ export class MfmService {
|
||||||
case 'article':
|
case 'article':
|
||||||
case 'li':
|
case 'li':
|
||||||
case 'dt':
|
case 'dt':
|
||||||
case 'dd':
|
case 'dd': {
|
||||||
{
|
|
||||||
text += '\n';
|
text += '\n';
|
||||||
appendChildren(node.childNodes);
|
appendChildren(node.childNodes);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
|
|
||||||
let forceError = localStorage.getItem('forceError');
|
let forceError = localStorage.getItem('forceError');
|
||||||
if (forceError != null) {
|
if (forceError != null) {
|
||||||
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.')
|
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Detect language & fetch translations
|
//#region Detect language & fetch translations
|
||||||
|
@ -155,7 +156,12 @@
|
||||||
document.head.appendChild(css);
|
document.head.appendChild(css);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderError(code, details) {
|
async function renderError(code, details) {
|
||||||
|
// Cannot set property 'innerHTML' of null を回避
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve));
|
||||||
|
}
|
||||||
|
|
||||||
let errorsElement = document.getElementById('errors');
|
let errorsElement = document.getElementById('errors');
|
||||||
|
|
||||||
if (!errorsElement) {
|
if (!errorsElement) {
|
||||||
|
@ -314,6 +320,6 @@
|
||||||
#errorInfo {
|
#errorInfo {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
`)
|
}`)
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -47,7 +47,6 @@ await fs.readFile(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, ''))
|
.map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, ''))
|
||||||
.map((path) => (path.startsWith('.') ? path : `./${path}`))
|
|
||||||
);
|
);
|
||||||
if (
|
if (
|
||||||
micromatch(Array.from(modules), [
|
micromatch(Array.from(modules), [
|
||||||
|
|
|
@ -184,10 +184,12 @@ export async function refreshAccount() {
|
||||||
|
|
||||||
export async function login(token: Account['token'], redirect?: string) {
|
export async function login(token: Account['token'], redirect?: string) {
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
|
||||||
success: false,
|
success: false,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
if (_DEV_) console.log('logging as token ', token);
|
if (_DEV_) console.log('logging as token ', token);
|
||||||
const me = await fetchAccount(token, undefined, true)
|
const me = await fetchAccount(token, undefined, true)
|
||||||
.catch(reason => {
|
.catch(reason => {
|
||||||
|
@ -223,21 +225,23 @@ export async function openAccountMenu(opts: {
|
||||||
if (!$i) return;
|
if (!$i) return;
|
||||||
|
|
||||||
function showSigninDialog() {
|
function showSigninDialog() {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
||||||
done: res => {
|
done: res => {
|
||||||
addAccount(res.id, res.i);
|
addAccount(res.id, res.i);
|
||||||
success();
|
success();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccount() {
|
function createAccount() {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
||||||
done: res => {
|
done: res => {
|
||||||
addAccount(res.id, res.i);
|
addAccount(res.id, res.i);
|
||||||
switchAccountWithToken(res.i);
|
switchAccountWithToken(res.i);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function switchAccount(account: Misskey.entities.UserDetailed) {
|
async function switchAccount(account: Misskey.entities.UserDetailed) {
|
||||||
|
|
|
@ -35,7 +35,9 @@ export async function mainBoot() {
|
||||||
emojiPicker.init();
|
emojiPicker.init();
|
||||||
|
|
||||||
if (isClientUpdated && $i) {
|
if (isClientUpdated && $i) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = useStream();
|
const stream = useStream();
|
||||||
|
@ -108,22 +110,28 @@ export async function mainBoot() {
|
||||||
|
|
||||||
defaultStore.loaded.then(() => {
|
defaultStore.loaded.then(() => {
|
||||||
if (defaultStore.state.accountSetupWizard !== -1) {
|
if (defaultStore.state.accountSetupWizard !== -1) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) {
|
for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
||||||
announcement,
|
announcement,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.on('announcementCreated', (ev) => {
|
stream.on('announcementCreated', (ev) => {
|
||||||
const announcement = ev.announcement;
|
const announcement = ev.announcement;
|
||||||
if (announcement.display === 'dialog') {
|
if (announcement.display === 'dialog') {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), {
|
||||||
announcement,
|
announcement,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -247,13 +255,17 @@ export async function mainBoot() {
|
||||||
const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
|
const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo');
|
||||||
if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) {
|
if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) {
|
||||||
if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) {
|
if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read');
|
||||||
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed');
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('Notification' in window) {
|
if ('Notification' in window) {
|
||||||
|
|
|
@ -35,7 +35,9 @@ const prevCookies = ref(0);
|
||||||
function onClick(ev: MouseEvent) {
|
function onClick(ev: MouseEvent) {
|
||||||
const x = ev.clientX;
|
const x = ev.clientX;
|
||||||
const y = ev.clientY;
|
const y = ev.clientY;
|
||||||
os.popup(MkPlusOneEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkPlusOneEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
saveData.value!.cookies++;
|
saveData.value!.cookies++;
|
||||||
saveData.value!.totalCookies++;
|
saveData.value!.totalCookies++;
|
||||||
|
|
|
@ -257,10 +257,11 @@ function onContextmenu(ev: MouseEvent) {
|
||||||
text: i18n.ts.openInWindow,
|
text: i18n.ts.openInWindow,
|
||||||
icon: 'ti ti-app-window',
|
icon: 'ti ti-app-window',
|
||||||
action: () => {
|
action: () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
|
||||||
initialFolder: props.folder,
|
initialFolder: props.folder,
|
||||||
}, {
|
}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}, { type: 'divider' }, {
|
}, { type: 'divider' }, {
|
||||||
text: i18n.ts.rename,
|
text: i18n.ts.rename,
|
||||||
|
|
|
@ -402,7 +402,9 @@ function chosen(emoji: any, ev?: MouseEvent) {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = getKey(emoji);
|
const key = getKey(emoji);
|
||||||
|
|
|
@ -37,11 +37,13 @@ const el = ref<HTMLElement | { $el: HTMLElement }>();
|
||||||
|
|
||||||
if (isEnabledUrlPreview.value) {
|
if (isEnabledUrlPreview.value) {
|
||||||
useTooltip(el, (showing) => {
|
useTooltip(el, (showing) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
||||||
showing,
|
showing,
|
||||||
url: props.url,
|
url: props.url,
|
||||||
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -335,12 +335,14 @@ if (!props.mock) {
|
||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkUsersTooltip, {
|
const { dispose } = os.popup(MkUsersTooltip, {
|
||||||
showing,
|
showing,
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.renoteCount,
|
count: appearNote.value.renoteCount,
|
||||||
targetElement: renoteButton.value,
|
targetElement: renoteButton.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||||
|
@ -355,13 +357,15 @@ if (!props.mock) {
|
||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkReactionsViewerDetails, {
|
const { dispose } = os.popup(MkReactionsViewerDetails, {
|
||||||
showing,
|
showing,
|
||||||
reaction: '❤️',
|
reaction: '❤️',
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.reactionCount,
|
count: appearNote.value.reactionCount,
|
||||||
targetElement: reactButton.value!,
|
targetElement: reactButton.value!,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,7 +413,9 @@ function react(viaKeyboard = false): void {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blur();
|
blur();
|
||||||
|
|
|
@ -346,12 +346,14 @@ useTooltip(renoteButton, async (showing) => {
|
||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkUsersTooltip, {
|
const { dispose } = os.popup(MkUsersTooltip, {
|
||||||
showing,
|
showing,
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.renoteCount,
|
count: appearNote.value.renoteCount,
|
||||||
targetElement: renoteButton.value,
|
targetElement: renoteButton.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||||
|
@ -366,13 +368,15 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') {
|
||||||
|
|
||||||
if (users.length < 1) return;
|
if (users.length < 1) return;
|
||||||
|
|
||||||
os.popup(MkReactionsViewerDetails, {
|
const { dispose } = os.popup(MkReactionsViewerDetails, {
|
||||||
showing,
|
showing,
|
||||||
reaction: '❤️',
|
reaction: '❤️',
|
||||||
users,
|
users,
|
||||||
count: appearNote.value.reactionCount,
|
count: appearNote.value.reactionCount,
|
||||||
targetElement: reactButton.value!,
|
targetElement: reactButton.value!,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +417,9 @@ function react(viaKeyboard = false): void {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blur();
|
blur();
|
||||||
|
|
|
@ -463,7 +463,7 @@ function setVisibility() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
|
||||||
currentVisibility: visibility.value,
|
currentVisibility: visibility.value,
|
||||||
isSilenced: $i.isSilenced,
|
isSilenced: $i.isSilenced,
|
||||||
localOnly: localOnly.value,
|
localOnly: localOnly.value,
|
||||||
|
@ -476,7 +476,8 @@ function setVisibility() {
|
||||||
defaultStore.set('visibility', visibility.value);
|
defaultStore.set('visibility', visibility.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleLocalOnly() {
|
async function toggleLocalOnly() {
|
||||||
|
@ -624,8 +625,8 @@ async function onPaste(ev: ClipboardEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, "0");
|
const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, '0');
|
||||||
const file = new File([paste], `${fileName}.txt`, { type: "text/plain" });
|
const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' });
|
||||||
upload(file, `${fileName}.txt`);
|
upload(file, `${fileName}.txt`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -731,7 +732,9 @@ async function post(ev?: MouseEvent) {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ async function rename(file) {
|
||||||
async function describe(file) {
|
async function describe(file) {
|
||||||
if (mock) return;
|
if (mock) return;
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
||||||
default: file.comment !== null ? file.comment : '',
|
default: file.comment !== null ? file.comment : '',
|
||||||
file: file,
|
file: file,
|
||||||
}, {
|
}, {
|
||||||
|
@ -121,7 +121,8 @@ async function describe(file) {
|
||||||
file.comment = comment;
|
file.comment = comment;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function crop(file: Misskey.entities.DriveFile): Promise<void> {
|
async function crop(file: Misskey.entities.DriveFile): Promise<void> {
|
||||||
|
|
|
@ -101,17 +101,19 @@ const steps = computed(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const onMousedown = (ev: MouseEvent | TouchEvent) => {
|
function onMousedown(ev: MouseEvent | TouchEvent) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const tooltipShowing = ref(true);
|
const tooltipShowing = ref(true);
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
||||||
showing: tooltipShowing,
|
showing: tooltipShowing,
|
||||||
text: computed(() => {
|
text: computed(() => {
|
||||||
return props.textConverter(finalValue.value);
|
return props.textConverter(finalValue.value);
|
||||||
}),
|
}),
|
||||||
targetElement: thumbEl,
|
targetElement: thumbEl,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
|
style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }'));
|
||||||
|
@ -152,7 +154,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => {
|
||||||
window.addEventListener('touchmove', onDrag);
|
window.addEventListener('touchmove', onDrag);
|
||||||
window.addEventListener('mouseup', onMouseup, { once: true });
|
window.addEventListener('mouseup', onMouseup, { once: true });
|
||||||
window.addEventListener('touchend', onMouseup, { once: true });
|
window.addEventListener('touchend', onMouseup, { once: true });
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -24,11 +24,13 @@ const elRef = shallowRef();
|
||||||
|
|
||||||
if (props.withTooltip) {
|
if (props.withTooltip) {
|
||||||
useTooltip(elRef, (showing) => {
|
useTooltip(elRef, (showing) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkReactionTooltip.vue')), {
|
||||||
showing,
|
showing,
|
||||||
reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
|
reaction: props.reaction.replace(/^:(\w+):$/, ':$1@.:'),
|
||||||
targetElement: elRef.value.$el,
|
targetElement: elRef.value.$el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -114,10 +114,12 @@ async function menu(ev) {
|
||||||
text: i18n.ts.info,
|
text: i18n.ts.info,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
os.popup(MkCustomEmojiDetailedDialog, {
|
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
|
||||||
emoji: await misskeyApiGet('emoji', {
|
emoji: await misskeyApiGet('emoji', {
|
||||||
name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
|
name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
|
||||||
}),
|
}),
|
||||||
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
|
@ -129,7 +131,9 @@ function anime() {
|
||||||
const rect = buttonEl.value.getBoundingClientRect();
|
const rect = buttonEl.value.getBoundingClientRect();
|
||||||
const x = rect.left + 16;
|
const x = rect.left + 16;
|
||||||
const y = rect.top + (buttonEl.value.offsetHeight / 2);
|
const y = rect.top + (buttonEl.value.offsetHeight / 2);
|
||||||
os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {}, 'end');
|
const { dispose } = os.popup(MkReactionEffect, { reaction: props.reaction, x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.count, (newCount, oldCount) => {
|
watch(() => props.count, (newCount, oldCount) => {
|
||||||
|
@ -151,13 +155,15 @@ if (!mock) {
|
||||||
|
|
||||||
const users = reactions.map(x => x.user);
|
const users = reactions.map(x => x.user);
|
||||||
|
|
||||||
os.popup(XDetails, {
|
const { dispose } = os.popup(XDetails, {
|
||||||
showing,
|
showing,
|
||||||
reaction: props.reaction,
|
reaction: props.reaction,
|
||||||
users,
|
users,
|
||||||
count: props.count,
|
count: props.count,
|
||||||
targetElement: buttonEl.value,
|
targetElement: buttonEl.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -218,8 +218,9 @@ function loginFailed(err: any): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetPassword(): void {
|
function resetPassword(): void {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,15 @@ export type MkSystemWebhookResult = {
|
||||||
|
|
||||||
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
|
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
|
||||||
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
|
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
|
||||||
const res = await os.popup(
|
const { dispose: _dispose } = os.popup(
|
||||||
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
|
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
|
||||||
props,
|
props,
|
||||||
{
|
{
|
||||||
submitted: (ev: MkSystemWebhookResult) => {
|
submitted: (ev: MkSystemWebhookResult) => {
|
||||||
resolve({ dispose: res.dispose, result: ev });
|
resolve({ dispose: _dispose, result: ev });
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve({ dispose: res.dispose, result: null });
|
resolve({ dispose: _dispose, result: null });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -188,11 +188,13 @@ function adjustTweetHeight(message: any) {
|
||||||
if (height) tweetHeight.value = height;
|
if (height) tweetHeight.value = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openPlayer = (): void => {
|
function openPlayer(): void {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
|
||||||
url: requestUrl.href,
|
url: requestUrl.href,
|
||||||
|
}, {
|
||||||
|
// TODO
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
(window as any).addEventListener('message', adjustTweetHeight);
|
(window as any).addEventListener('message', adjustTweetHeight);
|
||||||
|
|
||||||
|
|
|
@ -176,9 +176,11 @@ function setupComplete() {
|
||||||
function launchTutorial() {
|
function launchTutorial() {
|
||||||
setupComplete();
|
setupComplete();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
|
||||||
initialPage: 1,
|
initialPage: 1,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,15 +74,19 @@ misskeyApi('stats', {}).then((res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function signin() {
|
function signin() {
|
||||||
os.popup(XSigninDialog, {
|
const { dispose } = os.popup(XSigninDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function signup() {
|
function signup() {
|
||||||
os.popup(XSignupDialog, {
|
const { dispose } = os.popup(XSignupDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu(ev) {
|
function showMenu(ev) {
|
||||||
|
|
|
@ -106,12 +106,12 @@ function onClick(ev: MouseEvent) {
|
||||||
text: i18n.ts.info,
|
text: i18n.ts.info,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
os.popup(MkCustomEmojiDetailedDialog, {
|
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
|
||||||
emoji: await misskeyApiGet('emoji', {
|
emoji: await misskeyApiGet('emoji', {
|
||||||
name: customEmojiName.value,
|
name: customEmojiName.value,
|
||||||
}),
|
}),
|
||||||
}, {
|
}, {
|
||||||
anchor: ev.target,
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
|
|
|
@ -50,11 +50,13 @@ const el = ref();
|
||||||
|
|
||||||
if (props.showUrlPreview && isEnabledUrlPreview.value) {
|
if (props.showUrlPreview && isEnabledUrlPreview.value) {
|
||||||
useTooltip(el, (showing) => {
|
useTooltip(el, (showing) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), {
|
||||||
showing,
|
showing,
|
||||||
url: props.url,
|
url: props.url,
|
||||||
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
source: el.value instanceof HTMLElement ? el.value : el.value?.$el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,9 @@ export default {
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
|
|
||||||
popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,13 +51,15 @@ export default {
|
||||||
if (self.text == null) return;
|
if (self.text == null) return;
|
||||||
|
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), {
|
||||||
showing,
|
showing,
|
||||||
text: self.text,
|
text: self.text,
|
||||||
asMfm: binding.modifiers.mfm,
|
asMfm: binding.modifiers.mfm,
|
||||||
direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
|
direction: binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : binding.modifiers.top ? 'top' : binding.modifiers.bottom ? 'bottom' : 'top',
|
||||||
targetElement: el,
|
targetElement: el,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
self._close = () => {
|
self._close = () => {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
|
|
|
@ -35,7 +35,7 @@ export class UserPreview {
|
||||||
|
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
|
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserPopup.vue')), {
|
||||||
showing,
|
showing,
|
||||||
q: this.user,
|
q: this.user,
|
||||||
source: this.el,
|
source: this.el,
|
||||||
|
@ -47,7 +47,8 @@ export class UserPreview {
|
||||||
window.clearTimeout(this.showTimer);
|
window.clearTimeout(this.showTimer);
|
||||||
this.hideTimer = window.setTimeout(this.close, 500);
|
this.hideTimer = window.setTimeout(this.close, 500);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
this.promise = {
|
this.promise = {
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
|
|
|
@ -116,11 +116,13 @@ export function promiseDialog<T extends Promise<any>>(
|
||||||
});
|
});
|
||||||
|
|
||||||
// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
|
// NOTE: dynamic importすると挙動がおかしくなる(showingの変更が伝播しない)
|
||||||
popup(MkWaitingDialog, {
|
const { dispose } = popup(MkWaitingDialog, {
|
||||||
success: success,
|
success: success,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
text: text,
|
text: text,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
@ -166,28 +168,24 @@ type EmitsExtractor<T> = {
|
||||||
[K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize<E> : K extends string ? never : K]: T[K];
|
[K in keyof T as K extends `onVnode${string}` ? never : K extends `on${infer E}` ? Uncapitalize<E> : K extends string ? never : K]: T[K];
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function popup<T extends Component>(
|
export function popup<T extends Component>(
|
||||||
component: T,
|
component: T,
|
||||||
props: ComponentProps<T>,
|
props: ComponentProps<T>,
|
||||||
events: ComponentEmit<T> = {} as ComponentEmit<T>,
|
events: ComponentEmit<T> = {} as ComponentEmit<T>,
|
||||||
disposeEvent?: keyof ComponentEmit<T>,
|
): { dispose: () => void } {
|
||||||
): Promise<{ dispose: () => void }> {
|
|
||||||
markRaw(component);
|
markRaw(component);
|
||||||
|
|
||||||
const id = ++popupIdCount;
|
const id = ++popupIdCount;
|
||||||
const dispose = () => {
|
const dispose = () => {
|
||||||
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
|
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
popups.value = popups.value.filter(popup => popup.id !== id);
|
popups.value = popups.value.filter(p => p.id !== id);
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
const state = {
|
const state = {
|
||||||
component,
|
component,
|
||||||
props,
|
props,
|
||||||
events: disposeEvent ? {
|
events,
|
||||||
...events,
|
|
||||||
[disposeEvent]: dispose,
|
|
||||||
} : events,
|
|
||||||
id,
|
id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,15 +197,19 @@ export async function popup<T extends Component>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pageWindow(path: string) {
|
export function pageWindow(path: string) {
|
||||||
popup(MkPageWindow, {
|
const { dispose } = popup(MkPageWindow, {
|
||||||
initialPath: path,
|
initialPath: path,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toast(message: string) {
|
export function toast(message: string) {
|
||||||
popup(MkToast, {
|
const { dispose } = popup(MkToast, {
|
||||||
message,
|
message,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function alert(props: {
|
export function alert(props: {
|
||||||
|
@ -216,11 +218,12 @@ export function alert(props: {
|
||||||
text?: string;
|
text?: string;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, props, {
|
const { dispose } = popup(MkDialog, props, {
|
||||||
done: () => {
|
done: () => {
|
||||||
resolve();
|
resolve();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,14 +235,15 @@ export function confirm(props: {
|
||||||
cancelText?: string;
|
cancelText?: string;
|
||||||
}): Promise<{ canceled: boolean }> {
|
}): Promise<{ canceled: boolean }> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
...props,
|
...props,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +265,7 @@ export function actions<T extends {
|
||||||
canceled: false; result: T[number]['value'];
|
canceled: false; result: T[number]['value'];
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
...props,
|
...props,
|
||||||
actions: props.actions.map(a => ({
|
actions: props.actions.map(a => ({
|
||||||
text: a.text,
|
text: a.text,
|
||||||
|
@ -275,7 +279,8 @@ export function actions<T extends {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +328,7 @@ export function inputText(props: {
|
||||||
canceled: false; result: string | null;
|
canceled: false; result: string | null;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
input: {
|
input: {
|
||||||
|
@ -338,7 +343,8 @@ export function inputText(props: {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,7 +383,7 @@ export function inputNumber(props: {
|
||||||
canceled: false; result: number | null;
|
canceled: false; result: number | null;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
input: {
|
input: {
|
||||||
|
@ -390,7 +396,8 @@ export function inputNumber(props: {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +412,7 @@ export function inputDate(props: {
|
||||||
canceled: false; result: Date;
|
canceled: false; result: Date;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
input: {
|
input: {
|
||||||
|
@ -417,7 +424,8 @@ export function inputDate(props: {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
|
resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,11 +435,12 @@ export function authenticateDialog(): Promise<{
|
||||||
canceled: false; result: { password: string; token: string | null; };
|
canceled: false; result: { password: string; token: string | null; };
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkPasswordDialog, {}, {
|
const { dispose } = popup(MkPasswordDialog, {}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? { canceled: false, result } : { canceled: true, result: undefined });
|
resolve(result ? { canceled: false, result } : { canceled: true, result: undefined });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +485,7 @@ export function select<C = any>(props: {
|
||||||
canceled: false; result: C | null;
|
canceled: false; result: C | null;
|
||||||
}> {
|
}> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkDialog, {
|
const { dispose } = popup(MkDialog, {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
text: props.text,
|
text: props.text,
|
||||||
select: {
|
select: {
|
||||||
|
@ -487,7 +496,8 @@ export function select<C = any>(props: {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result ? result : { canceled: true });
|
resolve(result ? result : { canceled: true });
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,53 +507,57 @@ export function success(): Promise<void> {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
showing.value = false;
|
showing.value = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
popup(MkWaitingDialog, {
|
const { dispose } = popup(MkWaitingDialog, {
|
||||||
success: true,
|
success: true,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
}, {
|
}, {
|
||||||
done: () => resolve(),
|
done: () => resolve(),
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function waiting(): Promise<void> {
|
export function waiting(): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const showing = ref(true);
|
const showing = ref(true);
|
||||||
popup(MkWaitingDialog, {
|
const { dispose } = popup(MkWaitingDialog, {
|
||||||
success: false,
|
success: false,
|
||||||
showing: showing,
|
showing: showing,
|
||||||
}, {
|
}, {
|
||||||
done: () => resolve(),
|
done: () => resolve(),
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function form<F extends Form>(title: string, f: F): Promise<{ canceled: true, result?: undefined } | { canceled?: false, result: GetFormResultType<F> }> {
|
export function form<F extends Form>(title: string, f: F): Promise<{ canceled: true, result?: undefined } | { canceled?: false, result: GetFormResultType<F> }> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkFormDialog.vue')), { title, form: f }, {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkFormDialog.vue')), { title, form: f }, {
|
||||||
done: result => {
|
done: result => {
|
||||||
resolve(result);
|
resolve(result);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
|
export async function selectUser(opts: { includeSelf?: boolean; localOnly?: boolean; } = {}): Promise<Misskey.entities.UserDetailed> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSelectDialog.vue')), {
|
||||||
includeSelf: opts.includeSelf,
|
includeSelf: opts.includeSelf,
|
||||||
localOnly: opts.localOnly,
|
localOnly: opts.localOnly,
|
||||||
}, {
|
}, {
|
||||||
ok: user => {
|
ok: user => {
|
||||||
resolve(user);
|
resolve(user);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
export async function selectDriveFile(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
||||||
type: 'file',
|
type: 'file',
|
||||||
multiple,
|
multiple,
|
||||||
}, {
|
}, {
|
||||||
|
@ -552,13 +566,14 @@ export async function selectDriveFile(multiple: boolean): Promise<Misskey.entiti
|
||||||
resolve(files);
|
resolve(files);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
|
export async function selectDriveFolder(multiple: boolean): Promise<Misskey.entities.DriveFolder[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDriveSelectDialog.vue')), {
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
multiple,
|
multiple,
|
||||||
}, {
|
}, {
|
||||||
|
@ -567,20 +582,22 @@ export async function selectDriveFolder(multiple: boolean): Promise<Misskey.enti
|
||||||
resolve(folders);
|
resolve(folders);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
|
export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof MkEmojiPickerDialog>): Promise<string> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(MkEmojiPickerDialog, {
|
const { dispose } = popup(MkEmojiPickerDialog, {
|
||||||
src,
|
src,
|
||||||
...opts,
|
...opts,
|
||||||
}, {
|
}, {
|
||||||
done: emoji => {
|
done: emoji => {
|
||||||
resolve(emoji);
|
resolve(emoji);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,7 +606,7 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
|
||||||
uploadFolder?: string | null;
|
uploadFolder?: string | null;
|
||||||
}): Promise<Misskey.entities.DriveFile> {
|
}): Promise<Misskey.entities.DriveFile> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {
|
||||||
file: image,
|
file: image,
|
||||||
aspectRatio: options.aspectRatio,
|
aspectRatio: options.aspectRatio,
|
||||||
uploadFolder: options.uploadFolder,
|
uploadFolder: options.uploadFolder,
|
||||||
|
@ -597,7 +614,8 @@ export async function cropImage(image: Misskey.entities.DriveFile, options: {
|
||||||
ok: x => {
|
ok: x => {
|
||||||
resolve(x);
|
resolve(x);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,8 +626,7 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
|
||||||
onClosing?: () => void;
|
onClosing?: () => void;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let dispose;
|
const { dispose } = popup(MkPopupMenu, {
|
||||||
popup(MkPopupMenu, {
|
|
||||||
items,
|
items,
|
||||||
src,
|
src,
|
||||||
width: options?.width,
|
width: options?.width,
|
||||||
|
@ -623,8 +640,6 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
|
||||||
closing: () => {
|
closing: () => {
|
||||||
if (options?.onClosing) options.onClosing();
|
if (options?.onClosing) options.onClosing();
|
||||||
},
|
},
|
||||||
}).then(res => {
|
|
||||||
dispose = res.dispose;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -632,8 +647,7 @@ export function popupMenu(items: MenuItem[], src?: HTMLElement | EventTarget | n
|
||||||
export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let dispose;
|
const { dispose } = popup(MkContextMenu, {
|
||||||
popup(MkContextMenu, {
|
|
||||||
items,
|
items,
|
||||||
ev,
|
ev,
|
||||||
}, {
|
}, {
|
||||||
|
@ -641,8 +655,6 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
|
||||||
resolve();
|
resolve();
|
||||||
dispose();
|
dispose();
|
||||||
},
|
},
|
||||||
}).then(res => {
|
|
||||||
dispose = res.dispose;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -656,14 +668,11 @@ export function post(props: Record<string, any> = {}): Promise<void> {
|
||||||
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
|
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
|
||||||
// 複数のpost formを開いたときに場合によってはエラーになる
|
// 複数のpost formを開いたときに場合によってはエラーになる
|
||||||
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
|
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
|
||||||
let dispose;
|
const { dispose } = popup(MkPostFormDialog, props, {
|
||||||
popup(MkPostFormDialog, props, {
|
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve();
|
resolve();
|
||||||
dispose();
|
dispose();
|
||||||
},
|
},
|
||||||
}).then(res => {
|
|
||||||
dispose = res.dispose;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,16 +464,20 @@ function toggleRoleItem(role) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAnnouncement() {
|
function createAnnouncement() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
||||||
user: user.value,
|
user: user.value,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function editAnnouncement(announcement) {
|
function editAnnouncement(announcement) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
||||||
user: user.value,
|
user: user.value,
|
||||||
announcement,
|
announcement,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.userId, () => {
|
watch(() => props.userId, () => {
|
||||||
|
|
|
@ -109,7 +109,7 @@ async function onDeleteButtonClicked(id: string) {
|
||||||
|
|
||||||
async function showEditor(mode: 'create' | 'edit', id?: string) {
|
async function showEditor(mode: 'create' | 'edit', id?: string) {
|
||||||
const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
|
const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
|
||||||
const res = await os.popup(
|
const { dispose: _dispose } = os.popup(
|
||||||
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
|
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
|
||||||
{
|
{
|
||||||
mode,
|
mode,
|
||||||
|
@ -117,10 +117,10 @@ async function showEditor(mode: 'create' | 'edit', id?: string) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
submitted: async () => {
|
submitted: async () => {
|
||||||
resolve({ dispose: res.dispose, needLoad: true });
|
resolve({ dispose: _dispose, needLoad: true });
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve({ dispose: res.dispose, needLoad: false });
|
resolve({ dispose: _dispose, needLoad: false });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -129,18 +129,19 @@ const toggleSelect = (emoji) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const add = async (ev: MouseEvent) => {
|
const add = async (ev: MouseEvent) => {
|
||||||
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
if (result.created) {
|
if (result.created) {
|
||||||
emojisPaginationComponent.value.prepend(result.created);
|
emojisPaginationComponent.value.prepend(result.created);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = (emoji) => {
|
const edit = (emoji) => {
|
||||||
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
||||||
emoji: emoji,
|
emoji: emoji,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
|
@ -153,7 +154,8 @@ const edit = (emoji) => {
|
||||||
emojisPaginationComponent.value.removeItem(emoji.id);
|
emojisPaginationComponent.value.removeItem(emoji.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const importEmoji = (emoji) => {
|
const importEmoji = (emoji) => {
|
||||||
|
|
|
@ -160,7 +160,7 @@ function rename() {
|
||||||
function describe() {
|
function describe() {
|
||||||
if (!file.value) return;
|
if (!file.value) return;
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
||||||
default: file.value.comment ?? '',
|
default: file.value.comment ?? '',
|
||||||
file: file.value,
|
file: file.value,
|
||||||
}, {
|
}, {
|
||||||
|
@ -172,7 +172,8 @@ function describe() {
|
||||||
await fetch();
|
await fetch();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteFile() {
|
async function deleteFile() {
|
||||||
|
|
|
@ -1008,8 +1008,18 @@ function attachGameEvents() {
|
||||||
const domX = rect.left + (x * viewScale);
|
const domX = rect.left + (x * viewScale);
|
||||||
const domY = rect.top + (y * viewScale);
|
const domY = rect.top + (y * viewScale);
|
||||||
const scoreUnit = getScoreUnit(props.gameMode);
|
const scoreUnit = getScoreUnit(props.gameMode);
|
||||||
os.popup(MkRippleEffect, { x: domX, y: domY }, {}, 'end');
|
|
||||||
os.popup(MkPlusOneEffect, { x: domX, y: domY, value: scoreDelta + (scoreUnit === 'pt' ? '' : scoreUnit) }, {}, 'end');
|
{
|
||||||
|
const { dispose } = os.popup(MkRippleEffect, { x: domX, y: domY }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { dispose } = os.popup(MkPlusOneEffect, { x: domX, y: domY, value: scoreDelta + (scoreUnit === 'pt' ? '' : scoreUnit) }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (nextMono) {
|
if (nextMono) {
|
||||||
const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
|
const def = monoDefinitions.value.find(x => x.id === nextMono.id)!;
|
||||||
|
|
|
@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as os from '@/os.js';
|
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import * as os from '@/os.js';
|
||||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
|
@ -40,12 +40,12 @@ function menu(ev) {
|
||||||
text: i18n.ts.info,
|
text: i18n.ts.info,
|
||||||
icon: 'ti ti-info-circle',
|
icon: 'ti ti-info-circle',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
os.popup(MkCustomEmojiDetailedDialog, {
|
const { dispose } = os.popup(MkCustomEmojiDetailedDialog, {
|
||||||
emoji: await misskeyApiGet('emoji', {
|
emoji: await misskeyApiGet('emoji', {
|
||||||
name: props.emoji.name,
|
name: props.emoji.name,
|
||||||
})
|
}),
|
||||||
}, {
|
}, {
|
||||||
anchor: ev.target,
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
}], ev.currentTarget ?? ev.target);
|
||||||
|
|
|
@ -44,7 +44,9 @@ async function save() {
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.token == null) {
|
if (props.token == null) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {}, 'closed');
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
mainRouter.push('/');
|
mainRouter.push('/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -108,9 +108,11 @@ async function registerTOTP(): Promise<void> {
|
||||||
token: auth.result.token,
|
token: auth.result.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
|
||||||
twoFactorData,
|
twoFactorData,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unregisterTOTP(): Promise<void> {
|
async function unregisterTOTP(): Promise<void> {
|
||||||
|
|
|
@ -74,22 +74,24 @@ async function removeAccount(account) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addExistingAccount() {
|
function addExistingAccount() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
|
||||||
done: async res => {
|
done: async res => {
|
||||||
await addAccounts(res.id, res.i);
|
await addAccounts(res.id, res.i);
|
||||||
os.success();
|
os.success();
|
||||||
init();
|
init();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccount() {
|
function createAccount() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
|
||||||
done: async res => {
|
done: async res => {
|
||||||
await addAccounts(res.id, res.i);
|
await addAccounts(res.id, res.i);
|
||||||
switchAccountWithToken(res.i);
|
switchAccountWithToken(res.i);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function switchAccount(account: any) {
|
async function switchAccount(account: any) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
const isDesktop = ref(window.innerWidth >= 1100);
|
const isDesktop = ref(window.innerWidth >= 1100);
|
||||||
|
|
||||||
function generateToken() {
|
function generateToken() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
||||||
done: async result => {
|
done: async result => {
|
||||||
const { name, permissions } = result;
|
const { name, permissions } = result;
|
||||||
const { token } = await misskeyApi('miauth/gen-token', {
|
const { token } = await misskeyApi('miauth/gen-token', {
|
||||||
|
@ -38,7 +38,8 @@ function generateToken() {
|
||||||
text: token,
|
text: token,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = computed(() => []);
|
const headerActions = computed(() => []);
|
||||||
|
|
|
@ -67,7 +67,7 @@ misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function openDecoration(avatarDecoration, index?: number) {
|
function openDecoration(avatarDecoration, index?: number) {
|
||||||
os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
|
||||||
decoration: avatarDecoration,
|
decoration: avatarDecoration,
|
||||||
usingIndex: index,
|
usingIndex: index,
|
||||||
}, {
|
}, {
|
||||||
|
@ -108,7 +108,8 @@ function openDecoration(avatarDecoration, index?: number) {
|
||||||
});
|
});
|
||||||
$i.avatarDecorations = update;
|
$i.avatarDecorations = update;
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function detachAllDecorations() {
|
function detachAllDecorations() {
|
||||||
|
|
|
@ -27,7 +27,7 @@ function rename(file: Misskey.entities.DriveFile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function describe(file: Misskey.entities.DriveFile) {
|
function describe(file: Misskey.entities.DriveFile) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
||||||
default: file.comment ?? '',
|
default: file.comment ?? '',
|
||||||
file: file,
|
file: file,
|
||||||
}, {
|
}, {
|
||||||
|
@ -37,7 +37,8 @@ function describe(file: Misskey.entities.DriveFile) {
|
||||||
comment: caption.length === 0 ? null : caption,
|
comment: caption.length === 0 ? null : caption,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
function toggleSensitive(file: Misskey.entities.DriveFile) {
|
||||||
|
|
|
@ -136,10 +136,12 @@ export function getAbuseNoteMenu(note: Misskey.entities.Note, text: string): Men
|
||||||
let noteInfo = '';
|
let noteInfo = '';
|
||||||
if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
|
if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`;
|
||||||
noteInfo += `Local Note: ${localUrl}\n`;
|
noteInfo += `Local Note: ${localUrl}\n`;
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
||||||
user: note.user,
|
user: note.user,
|
||||||
initialComment: `${noteInfo}-----\n`,
|
initialComment: `${noteInfo}-----\n`,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -530,7 +532,9 @@ export function getRenoteMenu(props: {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.mock) {
|
if (!props.mock) {
|
||||||
|
@ -566,7 +570,9 @@ export function getRenoteMenu(props: {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
|
const configuredVisibility = defaultStore.state.rememberNoteVisibility ? defaultStore.state.visibility : defaultStore.state.defaultNoteVisibility;
|
||||||
|
@ -615,7 +621,9 @@ export function getRenoteMenu(props: {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
const { dispose } = os.popup(MkRippleEffect, { x, y }, {
|
||||||
|
end: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!props.mock) {
|
if (!props.mock) {
|
||||||
|
|
|
@ -100,9 +100,11 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportAbuse() {
|
function reportAbuse() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
||||||
user: user,
|
user: user,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getConfirmed(text: string): Promise<boolean> {
|
async function getConfirmed(text: string): Promise<boolean> {
|
||||||
|
|
|
@ -103,7 +103,7 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = realMeta.permissions == null || realMeta.permissions.length === 0 ? null : await new Promise((res, rej) => {
|
const token = realMeta.permissions == null || realMeta.permissions.length === 0 ? null : await new Promise((res, rej) => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
|
||||||
title: i18n.ts.tokenRequested,
|
title: i18n.ts.tokenRequested,
|
||||||
information: i18n.ts.pluginTokenRequestedDescription,
|
information: i18n.ts.pluginTokenRequestedDescription,
|
||||||
initialName: realMeta.name,
|
initialName: realMeta.name,
|
||||||
|
@ -118,7 +118,8 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
|
||||||
});
|
});
|
||||||
res(token);
|
res(token);
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
savePlugin({
|
savePlugin({
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { popup } from '@/os.js';
|
||||||
export function pleaseLogin(path?: string) {
|
export function pleaseLogin(path?: string) {
|
||||||
if ($i) return;
|
if ($i) return;
|
||||||
|
|
||||||
popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
|
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
message: i18n.ts.signinRequired,
|
message: i18n.ts.signinRequired,
|
||||||
}, {
|
}, {
|
||||||
|
@ -20,7 +20,8 @@ export function pleaseLogin(path?: string) {
|
||||||
window.location.href = path;
|
window.location.href = path;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
|
||||||
throw new Error('signin required');
|
throw new Error('signin required');
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,20 +17,16 @@ export function useChartTooltip(opts: { position: 'top' | 'middle' } = { positio
|
||||||
borderColor: string;
|
borderColor: string;
|
||||||
text: string;
|
text: string;
|
||||||
}[] | null>(null);
|
}[] | null>(null);
|
||||||
let disposeTooltipComponent;
|
const { dispose: disposeTooltipComponent } = os.popup(MkChartTooltip, {
|
||||||
|
|
||||||
os.popup(MkChartTooltip, {
|
|
||||||
showing: tooltipShowing,
|
showing: tooltipShowing,
|
||||||
x: tooltipX,
|
x: tooltipX,
|
||||||
y: tooltipY,
|
y: tooltipY,
|
||||||
title: tooltipTitle,
|
title: tooltipTitle,
|
||||||
series: tooltipSeries,
|
series: tooltipSeries,
|
||||||
}, {}).then(({ dispose }) => {
|
}, {});
|
||||||
disposeTooltipComponent = dispose;
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
if (disposeTooltipComponent) disposeTooltipComponent();
|
disposeTooltipComponent();
|
||||||
});
|
});
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
|
|
|
@ -112,7 +112,9 @@ export function openInstanceMenu(ev: MouseEvent) {
|
||||||
text: i18n.ts._initialTutorial.launchTutorial,
|
text: i18n.ts._initialTutorial.launchTutorial,
|
||||||
icon: 'ti ti-presentation',
|
icon: 'ti ti-presentation',
|
||||||
action: () => {
|
action: () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {}, 'closed');
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
} : undefined, {
|
} : undefined, {
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
|
|
@ -74,8 +74,9 @@ function openAccountMenu(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function more() {
|
function more() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -99,10 +99,11 @@ function openAccountMenu(ev: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
src: ev.currentTarget ?? ev.target,
|
||||||
}, {
|
}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -71,11 +71,12 @@ const otherNavItemIndicated = computed<boolean>(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
src: ev.currentTarget ?? ev.target,
|
||||||
anchor: { x: 'center', y: 'bottom' },
|
anchor: { x: 'center', y: 'bottom' },
|
||||||
}, {
|
}, {
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openAccountMenu(ev: MouseEvent) {
|
function openAccountMenu(ev: MouseEvent) {
|
||||||
|
|
|
@ -86,9 +86,11 @@ function calcViewState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
function more(ev: MouseEvent) {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
||||||
src: ev.currentTarget ?? ev.target,
|
src: ev.currentTarget ?? ev.target,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openAccountMenu(ev: MouseEvent) {
|
function openAccountMenu(ev: MouseEvent) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ const props = defineProps<{
|
||||||
const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
|
const notificationsComponent = shallowRef<InstanceType<typeof XNotifications>>();
|
||||||
|
|
||||||
function func() {
|
function func() {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
||||||
excludeTypes: props.column.excludeTypes,
|
excludeTypes: props.column.excludeTypes,
|
||||||
}, {
|
}, {
|
||||||
done: async (res) => {
|
done: async (res) => {
|
||||||
|
@ -36,7 +36,8 @@ function func() {
|
||||||
excludeTypes: excludeTypes,
|
excludeTypes: excludeTypes,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = [{
|
const menu = [{
|
||||||
|
|
|
@ -126,15 +126,19 @@ const keymap = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function signin() {
|
function signin() {
|
||||||
os.popup(XSigninDialog, {
|
const { dispose } = os.popup(XSigninDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function signup() {
|
function signup() {
|
||||||
os.popup(XSignupDialog, {
|
const { dispose } = os.popup(XSignupDialog, {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
}, {}, 'closed');
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -54,7 +54,7 @@ const { widgetProps, configure, save } = useWidgetPropsManager(name,
|
||||||
);
|
);
|
||||||
|
|
||||||
const configureNotification = () => {
|
const configureNotification = () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
||||||
excludeTypes: widgetProps.excludeTypes,
|
excludeTypes: widgetProps.excludeTypes,
|
||||||
}, {
|
}, {
|
||||||
done: async (res) => {
|
done: async (res) => {
|
||||||
|
@ -62,7 +62,8 @@ const configureNotification = () => {
|
||||||
widgetProps.excludeTypes = excludeTypes;
|
widgetProps.excludeTypes = excludeTypes;
|
||||||
save();
|
save();
|
||||||
},
|
},
|
||||||
}, 'closed');
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
defineExpose<WidgetComponentExpose>({
|
defineExpose<WidgetComponentExpose>({
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import dns from 'dns';
|
import dns from 'dns';
|
||||||
import { readFile } from 'node:fs/promises';
|
import { readFile } from 'node:fs/promises';
|
||||||
|
import type { IncomingMessage } from 'node:http';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
|
import type { UserConfig } from 'vite';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
import locales from '../../locales/index.js';
|
import locales from '../../locales/index.js';
|
||||||
import { getConfig } from './vite.config.js';
|
import { getConfig } from './vite.config.js';
|
||||||
|
@ -14,7 +16,15 @@ const { port } = yaml.load(await readFile('../../.config/default.yml', 'utf-8'))
|
||||||
const httpUrl = `http://localhost:${port}/`;
|
const httpUrl = `http://localhost:${port}/`;
|
||||||
const websocketUrl = `ws://localhost:${port}/`;
|
const websocketUrl = `ws://localhost:${port}/`;
|
||||||
|
|
||||||
const devConfig = {
|
// activitypubリクエストはProxyを通し、それ以外はViteの開発サーバーを返す
|
||||||
|
function varyHandler(req: IncomingMessage) {
|
||||||
|
if (req.headers.accept?.includes('application/activity+json')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return '/index.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
const devConfig: UserConfig = {
|
||||||
// 基本の設定は vite.config.js から引き継ぐ
|
// 基本の設定は vite.config.js から引き継ぐ
|
||||||
...defaultConfig,
|
...defaultConfig,
|
||||||
root: 'src',
|
root: 'src',
|
||||||
|
@ -54,15 +64,11 @@ const devConfig = {
|
||||||
'/inbox': httpUrl,
|
'/inbox': httpUrl,
|
||||||
'/notes': {
|
'/notes': {
|
||||||
target: httpUrl,
|
target: httpUrl,
|
||||||
headers: {
|
bypass: varyHandler,
|
||||||
'Accept': 'application/activity+json',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'/users': {
|
'/users': {
|
||||||
target: httpUrl,
|
target: httpUrl,
|
||||||
headers: {
|
bypass: varyHandler,
|
||||||
'Accept': 'application/activity+json',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
'/.well-known': {
|
'/.well-known': {
|
||||||
target: httpUrl,
|
target: httpUrl,
|
||||||
|
|
Loading…
Reference in New Issue