Compare commits
18 Commits
0e8e523d84
...
dd6f56edca
Author | SHA1 | Date |
---|---|---|
|
dd6f56edca | |
|
8d3a315645 | |
|
4a115c34ee | |
|
f4167ae7f1 | |
|
63db879bcc | |
|
70c71859f3 | |
|
8e9c9e9906 | |
|
66e93dcdd9 | |
|
bd17b465c3 | |
|
6b1fbf6819 | |
|
021c332097 | |
|
3691b69488 | |
|
5bdbff19ae | |
|
070a4516fc | |
|
c5d33661b2 | |
|
777ca15083 | |
|
21344f7695 | |
|
4254f52ced |
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,16 @@
|
||||||
|
## 2025.6.0
|
||||||
|
|
||||||
|
### General
|
||||||
|
-
|
||||||
|
|
||||||
|
### Client
|
||||||
|
- Enhance: 非同期的なコンポーネントの読み込み時のハンドリングを強化
|
||||||
|
- Fix: リアクションの一部の絵文字が重複して表示されることがある問題を修正
|
||||||
|
|
||||||
|
### Server
|
||||||
|
-
|
||||||
|
|
||||||
|
|
||||||
## 2025.5.1
|
## 2025.5.1
|
||||||
|
|
||||||
### Note
|
### Note
|
||||||
|
|
|
@ -1330,6 +1330,7 @@ restore: "Restaurar "
|
||||||
syncBetweenDevices: "Sincronització entre dispositius"
|
syncBetweenDevices: "Sincronització entre dispositius"
|
||||||
preferenceSyncConflictTitle: "Els valors de la configuració ja existeixen al dispositiu"
|
preferenceSyncConflictTitle: "Els valors de la configuració ja existeixen al dispositiu"
|
||||||
preferenceSyncConflictText: "Un element de la configuració amb sincronització activada desa els seus valors al servidor, però s'ha trobat un valor a la configuració desat al servidor per aquest element de la configuració. Quin valor us sobreescriure?"
|
preferenceSyncConflictText: "Un element de la configuració amb sincronització activada desa els seus valors al servidor, però s'ha trobat un valor a la configuració desat al servidor per aquest element de la configuració. Quin valor us sobreescriure?"
|
||||||
|
preferenceSyncConflictChoiceMerge: "Integració "
|
||||||
preferenceSyncConflictChoiceServer: "Valors de configuració del servidor"
|
preferenceSyncConflictChoiceServer: "Valors de configuració del servidor"
|
||||||
preferenceSyncConflictChoiceDevice: "Punts d'ajustos del dispositiu "
|
preferenceSyncConflictChoiceDevice: "Punts d'ajustos del dispositiu "
|
||||||
preferenceSyncConflictChoiceCancel: "Cancel·lar l'activació de la sincronització "
|
preferenceSyncConflictChoiceCancel: "Cancel·lar l'activació de la sincronització "
|
||||||
|
|
|
@ -1330,6 +1330,7 @@ restore: "Restore"
|
||||||
syncBetweenDevices: "Sync between devices"
|
syncBetweenDevices: "Sync between devices"
|
||||||
preferenceSyncConflictTitle: "The configured value exists on the server."
|
preferenceSyncConflictTitle: "The configured value exists on the server."
|
||||||
preferenceSyncConflictText: "The sync enabled settings will save their values to the server. However, there are existing values on the server. Which set of values would you like to overwrite?"
|
preferenceSyncConflictText: "The sync enabled settings will save their values to the server. However, there are existing values on the server. Which set of values would you like to overwrite?"
|
||||||
|
preferenceSyncConflictChoiceMerge: "Merge"
|
||||||
preferenceSyncConflictChoiceServer: "Configured value on server"
|
preferenceSyncConflictChoiceServer: "Configured value on server"
|
||||||
preferenceSyncConflictChoiceDevice: "Configured value on device"
|
preferenceSyncConflictChoiceDevice: "Configured value on device"
|
||||||
preferenceSyncConflictChoiceCancel: "Cancel enabling sync"
|
preferenceSyncConflictChoiceCancel: "Cancel enabling sync"
|
||||||
|
|
|
@ -3001,3 +3001,12 @@ _search:
|
||||||
pleaseEnterServerHost: "서버의 호스트를 입력해 주세요."
|
pleaseEnterServerHost: "서버의 호스트를 입력해 주세요."
|
||||||
pleaseSelectUser: "유저를 선택해주세요"
|
pleaseSelectUser: "유저를 선택해주세요"
|
||||||
serverHostPlaceholder: "예: misskey.example.com"
|
serverHostPlaceholder: "예: misskey.example.com"
|
||||||
|
_clientPerformanceIssueTip:
|
||||||
|
makeSureDisabledCustomCss: "커스텀 CSS를 무효로 해주십시오."
|
||||||
|
makeSureDisabledCustomCss_description: "스타일을 덮어쓰기하면 성능에 영향을 미칠 수 있습니다. 커스텀 CSS나 스타일을 덮어쓰기하는 확장 기능이 유효로 돼있는지 확인해주십시오."
|
||||||
|
makeSureDisabledAddons: "확장 기능을 무효로 해주십시오."
|
||||||
|
makeSureDisabledAddons_description: "일부 확장 기능은 클라이언트의 동작에 간섭해 성능에 영향을 미칠 수 있습니다. 브라우저의 확장 기능을 무효로 해 개선할지 확인해주십시오."
|
||||||
|
_clip:
|
||||||
|
tip: "클립은 노트를 정리할 수 있는 기능입니다."
|
||||||
|
_userLists:
|
||||||
|
tip: "임의의 유저가 포함된 리스트를 작성할 수 있습니다. 작성한 리스트는 타임라인으로 표시가 가능합니다."
|
||||||
|
|
|
@ -1330,6 +1330,7 @@ restore: "恢复"
|
||||||
syncBetweenDevices: "设备间同步"
|
syncBetweenDevices: "设备间同步"
|
||||||
preferenceSyncConflictTitle: "服务器上已存在设定值"
|
preferenceSyncConflictTitle: "服务器上已存在设定值"
|
||||||
preferenceSyncConflictText: "服务器上已有此设置的设定值。要覆盖哪个设定值?"
|
preferenceSyncConflictText: "服务器上已有此设置的设定值。要覆盖哪个设定值?"
|
||||||
|
preferenceSyncConflictChoiceMerge: "合并"
|
||||||
preferenceSyncConflictChoiceServer: "服务器上的设定值"
|
preferenceSyncConflictChoiceServer: "服务器上的设定值"
|
||||||
preferenceSyncConflictChoiceDevice: "设备上的设定值"
|
preferenceSyncConflictChoiceDevice: "设备上的设定值"
|
||||||
preferenceSyncConflictChoiceCancel: "取消同步"
|
preferenceSyncConflictChoiceCancel: "取消同步"
|
||||||
|
|
|
@ -327,6 +327,7 @@ dark: "深色"
|
||||||
lightThemes: "淺色佈景主題"
|
lightThemes: "淺色佈景主題"
|
||||||
darkThemes: "深色佈景主題"
|
darkThemes: "深色佈景主題"
|
||||||
syncDeviceDarkMode: "與裝置的深色模式同步"
|
syncDeviceDarkMode: "與裝置的深色模式同步"
|
||||||
|
switchDarkModeManuallyWhenSyncEnabledConfirm: "「{x}」已開啟。要關閉同步並手動切換模式嗎?\n"
|
||||||
drive: "雲端硬碟"
|
drive: "雲端硬碟"
|
||||||
fileName: "檔案名稱"
|
fileName: "檔案名稱"
|
||||||
selectFile: "選擇檔案"
|
selectFile: "選擇檔案"
|
||||||
|
@ -1329,6 +1330,7 @@ restore: "還原"
|
||||||
syncBetweenDevices: "裝置之間的同步化"
|
syncBetweenDevices: "裝置之間的同步化"
|
||||||
preferenceSyncConflictTitle: "伺服器上存在設定值"
|
preferenceSyncConflictTitle: "伺服器上存在設定值"
|
||||||
preferenceSyncConflictText: "已啟用同步的設定項目會將設定值儲存至伺服器,並已找到該設定項目在伺服器上儲存的設定值。請選擇要使用哪個設定值進行覆寫。"
|
preferenceSyncConflictText: "已啟用同步的設定項目會將設定值儲存至伺服器,並已找到該設定項目在伺服器上儲存的設定值。請選擇要使用哪個設定值進行覆寫。"
|
||||||
|
preferenceSyncConflictChoiceMerge: "合併至"
|
||||||
preferenceSyncConflictChoiceServer: "伺服器設定值"
|
preferenceSyncConflictChoiceServer: "伺服器設定值"
|
||||||
preferenceSyncConflictChoiceDevice: "裝置的設定值"
|
preferenceSyncConflictChoiceDevice: "裝置的設定值"
|
||||||
preferenceSyncConflictChoiceCancel: "取消啟用同步"
|
preferenceSyncConflictChoiceCancel: "取消啟用同步"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "2025.5.1-beta.6",
|
"version": "2025.6.0-alpha.0",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -282,8 +282,8 @@ function onContextmenu(ev: MouseEvent) {
|
||||||
menu = [{
|
menu = [{
|
||||||
text: i18n.ts.openInWindow,
|
text: i18n.ts.openInWindow,
|
||||||
icon: 'ti ti-app-window',
|
icon: 'ti ti-app-window',
|
||||||
action: () => {
|
action: async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkDriveWindow.vue').then(x => x.default), {
|
||||||
initialFolder: props.folder,
|
initialFolder: props.folder,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -113,7 +113,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<div v-if="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
|
<div v-if="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
|
||||||
<div v-if="draghover">{{ i18n.ts['empty-draghover'] }}</div>
|
<div v-if="draghover">{{ i18n.ts['empty-draghover'] }}</div>
|
||||||
<div v-if="!draghover && folder == null"><strong>{{ i18n.ts.emptyDrive }}</strong><br/>{{ i18n.ts['empty-drive-description'] }}</div>
|
<div v-if="!draghover && folder == null"><strong>{{ i18n.ts.emptyDrive }}</strong></div>
|
||||||
<div v-if="!draghover && folder != null">{{ i18n.ts.emptyFolder }}</div>
|
<div v-if="!draghover && folder != null">{{ i18n.ts.emptyFolder }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -126,7 +126,7 @@ async function rename(file) {
|
||||||
async function describe(file: Misskey.entities.DriveFile) {
|
async function describe(file: Misskey.entities.DriveFile) {
|
||||||
if (mock) return;
|
if (mock) return;
|
||||||
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkFileCaptionEditWindow.vue').then(x => x.default), {
|
||||||
default: file.comment !== null ? file.comment : '',
|
default: file.comment !== null ? file.comment : '',
|
||||||
file: file,
|
file: file,
|
||||||
}, {
|
}, {
|
||||||
|
@ -168,9 +168,11 @@ function showFileMenu(file: Misskey.entities.DriveFile, ev: MouseEvent | Keyboar
|
||||||
menuItems.push({
|
menuItems.push({
|
||||||
text: i18n.ts.preview,
|
text: i18n.ts.preview,
|
||||||
icon: 'ti ti-photo-search',
|
icon: 'ti ti-photo-search',
|
||||||
action: () => {
|
action: async () => {
|
||||||
os.popup(defineAsyncComponent(() => import('@/components/MkImgPreviewDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkImgPreviewDialog.vue').then(x => x.default), {
|
||||||
file: file,
|
file: file,
|
||||||
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -297,7 +297,7 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
icon: 'ti ti-sparkles',
|
icon: 'ti ti-sparkles',
|
||||||
text: i18n.ts._imageEffector.title,
|
text: i18n.ts._imageEffector.title,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkImageEffectorDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkImageEffectorDialog.vue').then(x => x.default), {
|
||||||
image: item.file,
|
image: item.file,
|
||||||
}, {
|
}, {
|
||||||
ok: (file) => {
|
ok: (file) => {
|
||||||
|
@ -349,7 +349,7 @@ function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
|
||||||
icon: 'ti ti-plus',
|
icon: 'ti ti-plus',
|
||||||
text: i18n.ts.add,
|
text: i18n.ts.add,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkWatermarkEditorDialog.vue').then(x => x.default), {
|
||||||
image: item.file,
|
image: item.file,
|
||||||
}, {
|
}, {
|
||||||
ok: (preset) => {
|
ok: (preset) => {
|
||||||
|
|
|
@ -174,8 +174,8 @@ function setupComplete() {
|
||||||
|
|
||||||
function launchTutorial() {
|
function launchTutorial() {
|
||||||
setupComplete();
|
setupComplete();
|
||||||
nextTick(() => {
|
nextTick(async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkTutorialDialog.vue').then(x => x.default), {
|
||||||
initialPage: 1,
|
initialPage: 1,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -185,7 +185,7 @@ async function edit(name: string) {
|
||||||
const emoji = await misskeyApi('emoji', {
|
const emoji = await misskeyApi('emoji', {
|
||||||
name: name,
|
name: name,
|
||||||
});
|
});
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/pages/emoji-edit-dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/pages/emoji-edit-dialog.vue').then(x => x.default), {
|
||||||
emoji: emoji,
|
emoji: emoji,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -196,7 +196,7 @@ export function useNoteCapture(props: {
|
||||||
}): {
|
}): {
|
||||||
$note: Reactive<ReactiveNoteData>;
|
$note: Reactive<ReactiveNoteData>;
|
||||||
subscribe: () => void;
|
subscribe: () => void;
|
||||||
} {
|
} {
|
||||||
const { note, parentNote, mock } = props;
|
const { note, parentNote, mock } = props;
|
||||||
|
|
||||||
const $note = reactive<ReactiveNoteData>({
|
const $note = reactive<ReactiveNoteData>({
|
||||||
|
@ -225,8 +225,8 @@ export function useNoteCapture(props: {
|
||||||
let latestPollVotedKey: string | null = null;
|
let latestPollVotedKey: string | null = null;
|
||||||
|
|
||||||
function onReacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }): void {
|
function onReacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }): void {
|
||||||
const normalizedName = ctx.reaction.replace(/^:(\w+):$/, ':$1@.:');
|
let normalizedName = ctx.reaction.replace(/^:(\w+):$/, ':$1@.:');
|
||||||
|
normalizedName = normalizedName.match('\u200d') ? normalizedName : normalizedName.replace(/\ufe0f/g, '');
|
||||||
if (reactionUserMap.has(ctx.userId) && reactionUserMap.get(ctx.userId) === normalizedName) return;
|
if (reactionUserMap.has(ctx.userId) && reactionUserMap.get(ctx.userId) === normalizedName) return;
|
||||||
reactionUserMap.set(ctx.userId, normalizedName);
|
reactionUserMap.set(ctx.userId, normalizedName);
|
||||||
|
|
||||||
|
@ -245,7 +245,8 @@ export function useNoteCapture(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUnreacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }): void {
|
function onUnreacted(ctx: { userId: Misskey.entities.User['id']; reaction: string; emoji?: { name: string; url: string; }; }): void {
|
||||||
const normalizedName = ctx.reaction.replace(/^:(\w+):$/, ':$1@.:');
|
let normalizedName = ctx.reaction.replace(/^:(\w+):$/, ':$1@.:');
|
||||||
|
normalizedName = normalizedName.match('\u200d') ? normalizedName : normalizedName.replace(/\ufe0f/g, '');
|
||||||
|
|
||||||
// 確実に一度リアクションされて取り消されている場合のみ処理をとめる(APIで初回読み込み→Streamでアップデート等の場合、reactionUserMapに情報がないため)
|
// 確実に一度リアクションされて取り消されている場合のみ処理をとめる(APIで初回読み込み→Streamでアップデート等の場合、reactionUserMapに情報がないため)
|
||||||
if (reactionUserMap.has(ctx.userId) && reactionUserMap.get(ctx.userId) === noReaction) return;
|
if (reactionUserMap.has(ctx.userId) && reactionUserMap.get(ctx.userId) === noReaction) return;
|
||||||
|
|
|
@ -206,6 +206,52 @@ export function popup<T extends Component>(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function popupAsyncWithDialog<T extends Component>(
|
||||||
|
componentFetching: Promise<T>,
|
||||||
|
props: ComponentProps<T>,
|
||||||
|
events: Partial<ComponentEmit<T>> = {},
|
||||||
|
): Promise<{ dispose: () => void }> {
|
||||||
|
const closeWaiting = waiting();
|
||||||
|
|
||||||
|
let component: T;
|
||||||
|
|
||||||
|
try {
|
||||||
|
component = await componentFetching;
|
||||||
|
} catch (err) {
|
||||||
|
closeWaiting();
|
||||||
|
alert({
|
||||||
|
type: 'error',
|
||||||
|
title: i18n.ts.somethingHappened,
|
||||||
|
text: 'CODE: ASYNC_COMP_LOAD_FAIL',
|
||||||
|
});
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeWaiting();
|
||||||
|
|
||||||
|
markRaw(component);
|
||||||
|
|
||||||
|
const id = ++popupIdCount;
|
||||||
|
const dispose = () => {
|
||||||
|
// このsetTimeoutが無いと挙動がおかしくなる(autocompleteが閉じなくなる)。Vueのバグ?
|
||||||
|
window.setTimeout(() => {
|
||||||
|
popups.value = popups.value.filter(p => p.id !== id);
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
component,
|
||||||
|
props,
|
||||||
|
events,
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
|
||||||
|
popups.value.push(state);
|
||||||
|
|
||||||
|
return {
|
||||||
|
dispose,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function pageWindow(path: string) {
|
export function pageWindow(path: string) {
|
||||||
const { dispose } = popup(MkPageWindow, {
|
const { dispose } = popup(MkPageWindow, {
|
||||||
initialPath: path,
|
initialPath: path,
|
||||||
|
@ -787,9 +833,9 @@ export function launchUploader(
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
},
|
},
|
||||||
): Promise<Misskey.entities.DriveFile[]> {
|
): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise(async (res, rej) => {
|
||||||
if (files.length === 0) return rej();
|
if (files.length === 0) return rej();
|
||||||
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUploaderDialog.vue')), {
|
const { dispose } = await popupAsyncWithDialog(import('@/components/MkUploaderDialog.vue').then(x => x.default), {
|
||||||
files: markRaw(files),
|
files: markRaw(files),
|
||||||
folderId: options?.folderId,
|
folderId: options?.folderId,
|
||||||
multiple: options?.multiple,
|
multiple: options?.multiple,
|
||||||
|
|
|
@ -391,6 +391,7 @@ const patrons = [
|
||||||
'asata',
|
'asata',
|
||||||
'ruru',
|
'ruru',
|
||||||
'みりめい',
|
'みりめい',
|
||||||
|
'東雲 琥珀',
|
||||||
];
|
];
|
||||||
|
|
||||||
const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));
|
const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));
|
||||||
|
|
|
@ -477,16 +477,16 @@ function toggleRoleItem(role) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAnnouncement() {
|
async function createAnnouncement() {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkUserAnnouncementEditDialog.vue').then(x => x.default), {
|
||||||
user: user.value,
|
user: user.value,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function editAnnouncement(announcement) {
|
async function editAnnouncement(announcement) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUserAnnouncementEditDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkUserAnnouncementEditDialog.vue').then(x => x.default), {
|
||||||
user: user.value,
|
user: user.value,
|
||||||
announcement,
|
announcement,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -525,10 +525,10 @@ const headerPageMetadata = computed(() => ({
|
||||||
const headerActions = computed(() => [{
|
const headerActions = computed(() => [{
|
||||||
icon: 'ti ti-search',
|
icon: 'ti ti-search',
|
||||||
text: i18n.ts.search,
|
text: i18n.ts.search,
|
||||||
handler: () => {
|
handler: async () => {
|
||||||
if (searchWindowOpening) return;
|
if (searchWindowOpening) return;
|
||||||
searchWindowOpening = true;
|
searchWindowOpening = true;
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./custom-emojis-manager.local.list.search.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./custom-emojis-manager.local.list.search.vue').then(x => x.default), {
|
||||||
query: searchQuery.value,
|
query: searchQuery.value,
|
||||||
}, {
|
}, {
|
||||||
queryUpdated: (query: EmojiSearchQuery) => {
|
queryUpdated: (query: EmojiSearchQuery) => {
|
||||||
|
@ -584,8 +584,8 @@ const headerActions = computed(() => [{
|
||||||
}, {
|
}, {
|
||||||
icon: 'ti ti-notes',
|
icon: 'ti ti-notes',
|
||||||
text: i18n.ts._customEmojisManager._gridCommon.registrationLogs,
|
text: i18n.ts._customEmojisManager._gridCommon.registrationLogs,
|
||||||
handler: () => {
|
handler: async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./custom-emojis-manager.local.list.logs.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./custom-emojis-manager.local.list.logs.vue').then(x => x.default), {
|
||||||
logs: requestLogs.value,
|
logs: requestLogs.value,
|
||||||
}, {
|
}, {
|
||||||
closed: () => {
|
closed: () => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ function load() {
|
||||||
load();
|
load();
|
||||||
|
|
||||||
async function add(ev: MouseEvent) {
|
async function add(ev: MouseEvent) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration-edit-dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./avatar-decoration-edit-dialog.vue').then(x => x.default), {
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
if (result.created) {
|
if (result.created) {
|
||||||
|
@ -57,8 +57,8 @@ async function add(ev: MouseEvent) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit(avatarDecoration) {
|
async function edit(avatarDecoration) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration-edit-dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./avatar-decoration-edit-dialog.vue').then(x => x.default), {
|
||||||
avatarDecoration: avatarDecoration,
|
avatarDecoration: avatarDecoration,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
|
|
|
@ -181,9 +181,9 @@ function showMenu(ev: MouseEvent, contextmenu = false) {
|
||||||
menu.push({
|
menu.push({
|
||||||
text: i18n.ts.reportAbuse,
|
text: i18n.ts.reportAbuse,
|
||||||
icon: 'ti ti-exclamation-circle',
|
icon: 'ti ti-exclamation-circle',
|
||||||
action: () => {
|
action: async () => {
|
||||||
const localUrl = `${url}/chat/messages/${props.message.id}`;
|
const localUrl = `${url}/chat/messages/${props.message.id}`;
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAbuseReportWindow.vue').then(x => x.default), {
|
||||||
user: props.message.fromUser!,
|
user: props.message.fromUser!,
|
||||||
initialComment: `${localUrl}\n-----\n`,
|
initialComment: `${localUrl}\n-----\n`,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -128,7 +128,7 @@ const toggleSelect = (emoji) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const add = async (ev: MouseEvent) => {
|
const add = async (ev: MouseEvent) => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./emoji-edit-dialog.vue').then(x => x.default), {
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
if (result.created) {
|
if (result.created) {
|
||||||
|
@ -139,8 +139,8 @@ const add = async (ev: MouseEvent) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const edit = (emoji) => {
|
const edit = async (emoji) => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./emoji-edit-dialog.vue').then(x => x.default), {
|
||||||
emoji: emoji,
|
emoji: emoji,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
|
|
|
@ -174,10 +174,10 @@ function rename() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function describe() {
|
async function describe() {
|
||||||
if (!file.value) return;
|
if (!file.value) return;
|
||||||
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkFileCaptionEditWindow.vue').then(x => x.default), {
|
||||||
default: file.value.comment ?? '',
|
default: file.value.comment ?? '',
|
||||||
file: file.value,
|
file: file.value,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -67,7 +67,7 @@ function menu(ev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const edit = async (emoji) => {
|
const edit = async (emoji) => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/pages/emoji-edit-dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/pages/emoji-edit-dialog.vue').then(x => x.default), {
|
||||||
emoji: emoji,
|
emoji: emoji,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -238,12 +238,12 @@ async function run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportAbuse() {
|
async function reportAbuse() {
|
||||||
if (!flash.value) return;
|
if (!flash.value) return;
|
||||||
|
|
||||||
const pageUrl = `${url}/play/${flash.value.id}`;
|
const pageUrl = `${url}/play/${flash.value.id}`;
|
||||||
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAbuseReportWindow.vue').then(x => x.default), {
|
||||||
user: flash.value.user,
|
user: flash.value.user,
|
||||||
initialComment: `Play: ${pageUrl}\n-----\n`,
|
initialComment: `Play: ${pageUrl}\n-----\n`,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -153,12 +153,12 @@ function edit() {
|
||||||
router.push(`/gallery/${post.value.id}/edit`);
|
router.push(`/gallery/${post.value.id}/edit`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportAbuse() {
|
async function reportAbuse() {
|
||||||
if (!post.value) return;
|
if (!post.value) return;
|
||||||
|
|
||||||
const pageUrl = `${url}/gallery/${post.value.id}`;
|
const pageUrl = `${url}/gallery/${post.value.id}`;
|
||||||
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAbuseReportWindow.vue').then(x => x.default), {
|
||||||
user: post.value.user,
|
user: post.value.user,
|
||||||
initialComment: `Post: ${pageUrl}\n-----\n`,
|
initialComment: `Post: ${pageUrl}\n-----\n`,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -245,12 +245,12 @@ function pin(pin) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportAbuse() {
|
async function reportAbuse() {
|
||||||
if (!page.value) return;
|
if (!page.value) return;
|
||||||
|
|
||||||
const pageUrl = `${url}/@${props.username}/pages/${props.pageName}`;
|
const pageUrl = `${url}/@${props.username}/pages/${props.pageName}`;
|
||||||
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAbuseReportWindow.vue').then(x => x.default), {
|
||||||
user: page.value.user,
|
user: page.value.user,
|
||||||
initialComment: `Page: ${pageUrl}\n-----\n`,
|
initialComment: `Page: ${pageUrl}\n-----\n`,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -41,9 +41,9 @@ async function save() {
|
||||||
mainRouter.push('/');
|
mainRouter.push('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
if (props.token == null) {
|
if (props.token == null) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkForgotPassword.vue')), {}, {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkForgotPassword.vue').then(x => x.default), {}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
mainRouter.push('/');
|
mainRouter.push('/');
|
||||||
|
|
|
@ -117,7 +117,7 @@ async function registerTOTP(): Promise<void> {
|
||||||
token: auth.result.token,
|
token: auth.result.token,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./2fa.qrdialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./2fa.qrdialog.vue').then(x => x.default), {
|
||||||
twoFactorData,
|
twoFactorData,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -68,8 +68,8 @@ misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
function openDecoration(avatarDecoration, index?: number) {
|
async function openDecoration(avatarDecoration, index?: number) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration.dialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('./avatar-decoration.dialog.vue').then(x => x.default), {
|
||||||
decoration: avatarDecoration,
|
decoration: avatarDecoration,
|
||||||
usingIndex: index,
|
usingIndex: index,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -81,8 +81,8 @@ const pagination = {
|
||||||
noPaging: true,
|
noPaging: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
function generateToken() {
|
async function generateToken() {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {}, {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkTokenGenerateWindow.vue').then(x => x.default), {}, {
|
||||||
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', {
|
||||||
|
|
|
@ -239,8 +239,8 @@ function chooseUploadFolder() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addWatermarkPreset() {
|
async function addWatermarkPreset() {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkWatermarkEditorDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkWatermarkEditorDialog.vue').then(x => x.default), {
|
||||||
}, {
|
}, {
|
||||||
ok: (preset: WatermarkPreset) => {
|
ok: (preset: WatermarkPreset) => {
|
||||||
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
|
prefer.commit('watermarkPresets', [...prefer.s.watermarkPresets, preset]);
|
||||||
|
|
|
@ -604,7 +604,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<MkInfo>
|
<MkInfo>
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<div>{{ i18n.ts._clientPerformanceIssueTip.title }}</div>
|
<div>{{ i18n.ts._clientPerformanceIssueTip.title }}:</div>
|
||||||
<div>
|
<div>
|
||||||
<div><b>{{ i18n.ts._clientPerformanceIssueTip.makeSureDisabledAdBlocker }}</b></div>
|
<div><b>{{ i18n.ts._clientPerformanceIssueTip.makeSureDisabledAdBlocker }}</b></div>
|
||||||
<div>{{ i18n.ts._clientPerformanceIssueTip.makeSureDisabledAdBlocker_description }}</div>
|
<div>{{ i18n.ts._clientPerformanceIssueTip.makeSureDisabledAdBlocker_description }}</div>
|
||||||
|
|
|
@ -95,8 +95,8 @@ export async function authorizePlugin(plugin: Plugin) {
|
||||||
if (plugin.permissions == null || plugin.permissions.length === 0) return;
|
if (plugin.permissions == null || plugin.permissions.length === 0) return;
|
||||||
if (Object.hasOwn(store.s.pluginTokens, plugin.installId)) return;
|
if (Object.hasOwn(store.s.pluginTokens, plugin.installId)) return;
|
||||||
|
|
||||||
const token = await new Promise<string>((res, rej) => {
|
const token = await new Promise<string>(async (res, rej) => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTokenGenerateWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkTokenGenerateWindow.vue').then(x => x.default), {
|
||||||
title: i18n.ts.tokenRequested,
|
title: i18n.ts.tokenRequested,
|
||||||
information: i18n.ts.pluginTokenRequestedDescription,
|
information: i18n.ts.pluginTokenRequestedDescription,
|
||||||
initialName: plugin.name,
|
initialName: plugin.name,
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import { hemisphere } from '@@/js/intl-const.js';
|
import { hemisphere } from '@@/js/intl-const.js';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import { definePreferences } from './manager.js';
|
||||||
import type { Theme } from '@/theme.js';
|
import type { Theme } from '@/theme.js';
|
||||||
import type { SoundType } from '@/utility/sound.js';
|
import type { SoundType } from '@/utility/sound.js';
|
||||||
import type { Plugin } from '@/plugin.js';
|
import type { Plugin } from '@/plugin.js';
|
||||||
import type { DeviceKind } from '@/utility/device-kind.js';
|
import type { DeviceKind } from '@/utility/device-kind.js';
|
||||||
import type { DeckProfile } from '@/deck.js';
|
import type { DeckProfile } from '@/deck.js';
|
||||||
import type { PreferencesDefinition } from './manager.js';
|
|
||||||
import type { WatermarkPreset } from '@/utility/watermark.js';
|
import type { WatermarkPreset } from '@/utility/watermark.js';
|
||||||
import { DEFAULT_DEVICE_KIND } from '@/utility/device-kind.js';
|
import { DEFAULT_DEVICE_KIND } from '@/utility/device-kind.js';
|
||||||
import { deepEqual } from '@/utility/deep-equal.js';
|
import { deepEqual } from '@/utility/deep-equal.js';
|
||||||
|
@ -34,7 +34,7 @@ export type SoundStore = {
|
||||||
|
|
||||||
// NOTE: デフォルト値は他の設定の状態に依存してはならない(依存していた場合、ユーザーがその設定項目単体で「初期値にリセット」した場合不具合の原因になる)
|
// NOTE: デフォルト値は他の設定の状態に依存してはならない(依存していた場合、ユーザーがその設定項目単体で「初期値にリセット」した場合不具合の原因になる)
|
||||||
|
|
||||||
export const PREF_DEF = {
|
export const PREF_DEF = definePreferences({
|
||||||
accounts: {
|
accounts: {
|
||||||
default: [] as [host: string, user: {
|
default: [] as [host: string, user: {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -89,7 +89,7 @@ export const PREF_DEF = {
|
||||||
emojis: string[];
|
emojis: string[];
|
||||||
}[],
|
}[],
|
||||||
mergeStrategy: (a, b) => {
|
mergeStrategy: (a, b) => {
|
||||||
const mergedItems = [] as (typeof a)[];
|
const mergedItems = [] as typeof a;
|
||||||
for (const x of a.concat(b)) {
|
for (const x of a.concat(b)) {
|
||||||
const sameIdItem = mergedItems.find(y => y.id === x.id);
|
const sameIdItem = mergedItems.find(y => y.id === x.id);
|
||||||
if (sameIdItem != null) {
|
if (sameIdItem != null) {
|
||||||
|
@ -120,7 +120,7 @@ export const PREF_DEF = {
|
||||||
themes: {
|
themes: {
|
||||||
default: [] as Theme[],
|
default: [] as Theme[],
|
||||||
mergeStrategy: (a, b) => {
|
mergeStrategy: (a, b) => {
|
||||||
const mergedItems = [] as (typeof a)[];
|
const mergedItems = [] as typeof a;
|
||||||
for (const x of a.concat(b)) {
|
for (const x of a.concat(b)) {
|
||||||
const sameIdItem = mergedItems.find(y => y.id === x.id);
|
const sameIdItem = mergedItems.find(y => y.id === x.id);
|
||||||
if (sameIdItem != null) {
|
if (sameIdItem != null) {
|
||||||
|
@ -398,7 +398,7 @@ export const PREF_DEF = {
|
||||||
accountDependent: true,
|
accountDependent: true,
|
||||||
default: [] as WatermarkPreset[],
|
default: [] as WatermarkPreset[],
|
||||||
mergeStrategy: (a, b) => {
|
mergeStrategy: (a, b) => {
|
||||||
const mergedItems = [] as (typeof a)[];
|
const mergedItems = [] as typeof a;
|
||||||
for (const x of a.concat(b)) {
|
for (const x of a.concat(b)) {
|
||||||
const sameIdItem = mergedItems.find(y => y.id === x.id);
|
const sameIdItem = mergedItems.find(y => y.id === x.id);
|
||||||
if (sameIdItem != null) {
|
if (sameIdItem != null) {
|
||||||
|
@ -492,4 +492,4 @@ export const PREF_DEF = {
|
||||||
'experimental.enableFolderPageView': {
|
'experimental.enableFolderPageView': {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
} satisfies PreferencesDefinition;
|
});
|
||||||
|
|
|
@ -96,6 +96,14 @@ type PreferencesDefinitionRecord<Default, T = Default extends (...args: any) =>
|
||||||
|
|
||||||
export type PreferencesDefinition = Record<string, PreferencesDefinitionRecord<any>>;
|
export type PreferencesDefinition = Record<string, PreferencesDefinitionRecord<any>>;
|
||||||
|
|
||||||
|
export function definePreferences<T extends Record<string, unknown>>(x: {
|
||||||
|
[K in keyof T]: PreferencesDefinitionRecord<T[K]>
|
||||||
|
}): {
|
||||||
|
[K in keyof T]: PreferencesDefinitionRecord<T[K]>
|
||||||
|
} {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
export function getInitialPrefValue<K extends keyof PREF>(k: K): ValueOf<K> {
|
export function getInitialPrefValue<K extends keyof PREF>(k: K): ValueOf<K> {
|
||||||
if (typeof PREF_DEF[k].default === 'function') { // factory
|
if (typeof PREF_DEF[k].default === 'function') { // factory
|
||||||
return PREF_DEF[k].default();
|
return PREF_DEF[k].default();
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent } from 'vue';
|
||||||
|
import { host } from '@@/js/config.js';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import { host } from '@@/js/config.js';
|
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
|
|
||||||
|
@ -146,8 +146,8 @@ export function openInstanceMenu(ev: MouseEvent) {
|
||||||
menuItems.push({
|
menuItems.push({
|
||||||
text: i18n.ts._initialTutorial.launchTutorial,
|
text: i18n.ts._initialTutorial.launchTutorial,
|
||||||
icon: 'ti ti-presentation',
|
icon: 'ti ti-presentation',
|
||||||
action: () => {
|
action: async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTutorialDialog.vue')), {}, {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkTutorialDialog.vue').then(x => x.default), {}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -71,8 +71,8 @@ const otherNavItemIndicated = computed<boolean>(() => {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
async function more(ev: MouseEvent) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkLaunchPad.vue').then(x => x.default), {
|
||||||
anchorElement: ev.currentTarget ?? ev.target,
|
anchorElement: ev.currentTarget ?? ev.target,
|
||||||
anchor: { x: 'center', y: 'bottom' },
|
anchor: { x: 'center', y: 'bottom' },
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -176,10 +176,10 @@ function openAccountMenu(ev: MouseEvent) {
|
||||||
}, ev);
|
}, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
function more(ev: MouseEvent) {
|
async function more(ev: MouseEvent) {
|
||||||
const target = getHTMLElementOrNull(ev.currentTarget ?? ev.target);
|
const target = getHTMLElementOrNull(ev.currentTarget ?? ev.target);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkLaunchPad.vue').then(x => x.default), {
|
||||||
anchorElement: target,
|
anchorElement: target,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -72,7 +72,7 @@ async function setAntenna() {
|
||||||
if (canceled || antenna == null) return;
|
if (canceled || antenna == null) return;
|
||||||
|
|
||||||
if (antenna === '_CREATE_') {
|
if (antenna === '_CREATE_') {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAntennaEditorDialog.vue')), {}, {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAntennaEditorDialog.vue').then(x => x.default), {}, {
|
||||||
created: (newAntenna: MisskeyEntities.Antenna) => {
|
created: (newAntenna: MisskeyEntities.Antenna) => {
|
||||||
antennasCache.delete();
|
antennasCache.delete();
|
||||||
updateColumn(props.column.id, {
|
updateColumn(props.column.id, {
|
||||||
|
|
|
@ -27,8 +27,8 @@ const props = defineProps<{
|
||||||
|
|
||||||
const notificationsComponent = useTemplateRef('notificationsComponent');
|
const notificationsComponent = useTemplateRef('notificationsComponent');
|
||||||
|
|
||||||
function func() {
|
async function func() {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkNotificationSelectWindow.vue').then(x => x.default), {
|
||||||
excludeTypes: props.column.excludeTypes,
|
excludeTypes: props.column.excludeTypes,
|
||||||
}, {
|
}, {
|
||||||
done: async (res) => {
|
done: async (res) => {
|
||||||
|
|
|
@ -172,8 +172,8 @@ export function chooseFileFromPcAndUpload(
|
||||||
export function chooseDriveFile(options: {
|
export function chooseDriveFile(options: {
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
} = {}): Promise<Misskey.entities.DriveFile[]> {
|
} = {}): Promise<Misskey.entities.DriveFile[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(async resolve => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveFileSelectDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkDriveFileSelectDialog.vue').then(x => x.default), {
|
||||||
multiple: options.multiple ?? false,
|
multiple: options.multiple ?? false,
|
||||||
}, {
|
}, {
|
||||||
done: files => {
|
done: files => {
|
||||||
|
@ -286,8 +286,8 @@ export async function createCroppedImageDriveFileFromImageDriveFile(imageDriveFi
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectDriveFolder(initialFolder: Misskey.entities.DriveFolder['id'] | null): Promise<Misskey.entities.DriveFolder[]> {
|
export async function selectDriveFolder(initialFolder: Misskey.entities.DriveFolder['id'] | null): Promise<Misskey.entities.DriveFolder[]> {
|
||||||
return new Promise(resolve => {
|
return new Promise(async resolve => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveFolderSelectDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkDriveFolderSelectDialog.vue').then(x => x.default), {
|
||||||
initialFolder,
|
initialFolder,
|
||||||
}, {
|
}, {
|
||||||
done: folders => {
|
done: folders => {
|
||||||
|
|
|
@ -28,8 +28,8 @@ function rename(file: Misskey.entities.DriveFile) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function describe(file: Misskey.entities.DriveFile) {
|
async function describe(file: Misskey.entities.DriveFile) {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkFileCaptionEditWindow.vue').then(x => x.default), {
|
||||||
default: file.comment ?? '',
|
default: file.comment ?? '',
|
||||||
file: file,
|
file: file,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -64,7 +64,7 @@ export function getEmbedCode(path: string, params?: EmbedParams): string {
|
||||||
*
|
*
|
||||||
* カスタマイズ機能がいらない場合(事前にパラメータを指定する場合)は getEmbedCode を直接使ってください
|
* カスタマイズ機能がいらない場合(事前にパラメータを指定する場合)は getEmbedCode を直接使ってください
|
||||||
*/
|
*/
|
||||||
export function genEmbedCode(entity: EmbeddableEntity, id: string, params?: EmbedParams) {
|
export async function genEmbedCode(entity: EmbeddableEntity, id: string, params?: EmbedParams) {
|
||||||
const _params = { ...params };
|
const _params = { ...params };
|
||||||
|
|
||||||
if (embedRouteWithScrollbar.includes(entity) && _params.maxHeight == null) {
|
if (embedRouteWithScrollbar.includes(entity) && _params.maxHeight == null) {
|
||||||
|
@ -75,7 +75,7 @@ export function genEmbedCode(entity: EmbeddableEntity, id: string, params?: Embe
|
||||||
if (window.innerWidth < MOBILE_THRESHOLD) {
|
if (window.innerWidth < MOBILE_THRESHOLD) {
|
||||||
copyToClipboard(getEmbedCode(`/embed/${entity}/${id}`, _params));
|
copyToClipboard(getEmbedCode(`/embed/${entity}/${id}`, _params));
|
||||||
} else {
|
} else {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkEmbedCodeGenDialog.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkEmbedCodeGenDialog.vue').then(x => x.default), {
|
||||||
entity,
|
entity,
|
||||||
id,
|
id,
|
||||||
params: _params,
|
params: _params,
|
||||||
|
|
|
@ -135,12 +135,12 @@ export function getAbuseNoteMenu(note: Misskey.entities.Note, text: string): Men
|
||||||
return {
|
return {
|
||||||
icon: 'ti ti-exclamation-circle',
|
icon: 'ti ti-exclamation-circle',
|
||||||
text,
|
text,
|
||||||
action: (): void => {
|
action: async (): Promise<void> => {
|
||||||
const localUrl = `${url}/notes/${note.id}`;
|
const localUrl = `${url}/notes/${note.id}`;
|
||||||
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`;
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAbuseReportWindow.vue').then(x => x.default), {
|
||||||
user: note.user,
|
user: note.user,
|
||||||
initialComment: `${noteInfo}-----\n`,
|
initialComment: `${noteInfo}-----\n`,
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -94,8 +94,8 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function reportAbuse() {
|
async function reportAbuse() {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkAbuseReportWindow.vue').then(x => x.default), {
|
||||||
user: user,
|
user: user,
|
||||||
}, {
|
}, {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
|
|
|
@ -387,6 +387,9 @@ export class ImageEffector {
|
||||||
this.gl.deleteProgram(this.renderTextureProgram);
|
this.gl.deleteProgram(this.renderTextureProgram);
|
||||||
this.gl.deleteProgram(this.renderInvertedTextureProgram);
|
this.gl.deleteProgram(this.renderInvertedTextureProgram);
|
||||||
this.gl.deleteTexture(this.originalImageTexture);
|
this.gl.deleteTexture(this.originalImageTexture);
|
||||||
|
|
||||||
|
const loseContextExt = this.gl.getExtension('WEBGL_lose_context');
|
||||||
|
if (loseContextExt) loseContextExt.loseContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defineAsyncComponent } from 'vue';
|
|
||||||
import { $i } from '@/i.js';
|
import { $i } from '@/i.js';
|
||||||
import { instance } from '@/instance.js';
|
import { instance } from '@/instance.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { popup } from '@/os.js';
|
import { popupAsyncWithDialog } from '@/os.js';
|
||||||
|
|
||||||
export type OpenOnRemoteOptions = {
|
export type OpenOnRemoteOptions = {
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +44,7 @@ export type OpenOnRemoteOptions = {
|
||||||
params: Record<string, string>;
|
params: Record<string, string>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function pleaseLogin(opts: {
|
export async function pleaseLogin(opts: {
|
||||||
path?: string;
|
path?: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
openOnRemote?: OpenOnRemoteOptions;
|
openOnRemote?: OpenOnRemoteOptions;
|
||||||
|
@ -59,7 +58,7 @@ export function pleaseLogin(opts: {
|
||||||
_openOnRemote = opts.openOnRemote;
|
_openOnRemote = opts.openOnRemote;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
|
const { dispose } = await popupAsyncWithDialog(import('@/components/MkSigninDialog.vue').then(x => x.default), {
|
||||||
autoSet: true,
|
autoSet: true,
|
||||||
message: opts.message ?? (_openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired),
|
message: opts.message ?? (_openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired),
|
||||||
openOnRemote: _openOnRemote,
|
openOnRemote: _openOnRemote,
|
||||||
|
|
|
@ -54,8 +54,8 @@ const { widgetProps, configure, save } = useWidgetPropsManager(name,
|
||||||
emit,
|
emit,
|
||||||
);
|
);
|
||||||
|
|
||||||
const configureNotification = () => {
|
const configureNotification = async () => {
|
||||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNotificationSelectWindow.vue')), {
|
const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkNotificationSelectWindow.vue').then(x => x.default), {
|
||||||
excludeTypes: widgetProps.excludeTypes,
|
excludeTypes: widgetProps.excludeTypes,
|
||||||
}, {
|
}, {
|
||||||
done: async (res) => {
|
done: async (res) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"name": "misskey-js",
|
"name": "misskey-js",
|
||||||
"version": "2025.5.1-beta.6",
|
"version": "2025.6.0-alpha.0",
|
||||||
"description": "Misskey SDK for JavaScript",
|
"description": "Misskey SDK for JavaScript",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./built/index.js",
|
"main": "./built/index.js",
|
||||||
|
|
Loading…
Reference in New Issue