popupの制御を出す側で行うように

This commit is contained in:
kakkokari-gtyih 2024-07-15 11:53:32 +09:00
parent 8d144c8fdc
commit 87a7d1a8ea
10 changed files with 52 additions and 52 deletions

View File

@ -18,11 +18,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<!--<div v-if="appearNote._featuredId_" class="tip"><i class="ti ti-bolt"></i> {{ i18n.ts.featured }}</div>-->
<div v-if="isRenote" :class="$style.renote">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link :preview="!inEmbedPage && !mock"/>
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
<I18n :src="i18n.ts.renotedBy" tag="span" :class="$style.renoteText">
<template #user>
<MkA v-user-preview="note.userId" :class="$style.renoteUserName" :to="userPage(note.user)">
<MkA v-user-preview="inEmbedPage ? undefined : note.userId" :class="$style.renoteUserName" :to="userPage(note.user)">
<MkUserName :user="note.user"/>
</MkA>
</template>
@ -42,12 +42,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link :preview="!inEmbedPage && !mock"/>
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
</div>
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
<MkAvatar :class="$style.avatar" :user="appearNote.user" :link="!mock" :preview="!mock"/>
<MkAvatar :class="$style.avatar" :user="appearNote.user" :link="!mock" :preview="!inEmbedPage && !mock"/>
<div :class="$style.main">
<MkNoteHeader :note="appearNote" :mini="true"/>
<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:author="appearNote.user"
:nyaize="'respect'"
:emojiUrls="appearNote.emojis"
:enableEmojiMenu="true"
:enableEmojiMenu="!inEmbedPage"
:enableEmojiMenuReaction="true"
/>
<div v-if="translating || translation" :class="$style.translation">
@ -81,8 +81,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files" :originalEntityUrl="`${url}/notes/${appearNote.id}`"/>
</div>
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/>
<div v-if="isEnabledUrlPreview && !inEmbedPage">
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :readOnly="inEmbedPage" :class="$style.poll"/>
<div v-if="isEnabledUrlPreview">
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
@ -156,14 +156,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-else-if="!hardMuted" :class="$style.muted" @click="muted = false">
<I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small">
<template #name>
<MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)">
<MkA v-user-preview="inEmbedPage ? undefined : appearNote.userId" :to="userPage(appearNote.user)">
<MkUserName :user="appearNote.user"/>
</MkA>
</template>
</I18n>
<I18n v-else :src="i18n.ts.userSaysSomething" tag="small">
<template #name>
<MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)">
<MkA v-user-preview="inEmbedPage ? undefined : appearNote.userId" :to="userPage(appearNote.user)">
<MkUserName :user="appearNote.user"/>
</MkA>
</template>

View File

@ -11,12 +11,12 @@ SPDX-License-Identifier: AGPL-3.0-only
>
<MkNoteSub v-if="appearNote.reply" :note="appearNote.reply" :class="$style.replyTo"/>
<div v-if="isRenote" :class="$style.renote">
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link preview/>
<MkAvatar :class="$style.renoteAvatar" :user="note.user" link/>
<i class="ti ti-repeat" style="margin-right: 4px;"></i>
<span :class="$style.renoteText">
<I18n :src="i18n.ts.renotedBy" tag="span">
<template #user>
<MkA v-user-preview="note.userId" :class="$style.renoteName" :to="userPage(note.user)">
<MkA :class="$style.renoteName" :to="userPage(note.user)">
<MkUserName :user="note.user"/>
</MkA>
</template>
@ -36,12 +36,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<article :class="$style.note">
<header :class="$style.noteHeader">
<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link preview/>
<MkAvatar :class="$style.noteHeaderAvatar" :user="appearNote.user" indicator link/>
<div :class="$style.noteHeaderBody">
<div :class="$style.noteHeaderBodyUpper">
<div style="min-width: 0;">
<div class="_nowrap">
<MkA v-user-preview="appearNote.user.id" :class="$style.noteHeaderName" :to="userPage(appearNote.user)">
<MkA :class="$style.noteHeaderName" :to="userPage(appearNote.user)">
<MkUserName :nowrap="true" :user="appearNote.user"/>
</MkA>
<span v-if="appearNote.user.isBot" :class="$style.isBot">bot</span>
@ -72,14 +72,12 @@ SPDX-License-Identifier: AGPL-3.0-only
:author="appearNote.user"
:nyaize="'respect'"
:emojiUrls="appearNote.emojis"
:enableEmojiMenu="true"
:enableEmojiMenuReaction="true"
/>
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList :mediaList="appearNote.files" :originalEntityUrl="`${url}/notes/${appearNote.id}`"/>
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :readOnly="true" :class="$style.poll"/>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
<button v-if="isLong && collapsed" :class="$style.collapsed" class="_button" @click="collapsed = false">
<span :class="$style.collapsedLabel">{{ i18n.ts.showMore }}</span>

View File

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="mock" :class="$style.name">
<MkUserName :user="note.user"/>
</div>
<MkA v-else v-user-preview="note.user.id" :class="$style.name" :to="userPage(note.user)">
<MkA v-else v-user-preview="inEmbedPage ? undefined : note.user.id" :class="$style.name" :to="userPage(note.user)">
<MkUserName :user="note.user"/>
</MkA>
<div v-if="note.user.isBot" :class="$style.isBot">bot</div>
@ -46,6 +46,7 @@ defineProps<{
}>();
const mock = inject<boolean>('mock', false);
const inEmbedPage = inject<boolean>('EMBED_PAGE', false);
</script>
<style lang="scss" module>

View File

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div :class="$style.root">
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>
<MkAvatar :class="$style.avatar" :user="note.user" link :preview="!inEmbedPage"/>
<div :class="$style.main">
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ref, inject } from 'vue';
import * as Misskey from 'misskey-js';
import MkNoteHeader from '@/components/MkNoteHeader.vue';
import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
@ -32,6 +32,8 @@ const props = defineProps<{
note: Misskey.entities.Note;
}>();
const inEmbedPage = inject<boolean>('EMBED_PAGE', false);
const showContent = ref(false);
</script>

View File

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="!muted" :class="[$style.root, { [$style.children]: depth > 1 }]">
<div :class="$style.main">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>
<MkAvatar :class="$style.avatar" :user="note.user" link :preview="!inEmbedPage"/>
<div :class="$style.body">
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ref, inject } from 'vue';
import * as Misskey from 'misskey-js';
import MkNoteHeader from '@/components/MkNoteHeader.vue';
import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
@ -62,6 +62,8 @@ const props = withDefaults(defineProps<{
depth: 1,
});
const inEmbedPage = inject<boolean>('EMBED_PAGE', false);
const muted = ref($i ? checkWordMute(props.note, $i, $i.mutedWords) : false);
const showContent = ref(false);

View File

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="{ [$style.done]: closed || isVoted }">
<div :class="{ [$style.done]: closed || isVoted || readOnly }">
<ul :class="$style.choices">
<li v-for="(choice, i) in poll.choices" :key="i" :class="$style.choice" @click="vote(i)">
<div :class="$style.bg" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div>
@ -83,10 +83,10 @@ if (props.poll.expiresAt) {
}
const vote = async (id) => {
pleaseLogin(undefined, pleaseLoginContext.value);
if (props.readOnly || closed.value || isVoted.value) return;
pleaseLogin(undefined, pleaseLoginContext.value);
const { canceled } = await os.confirm({
type: 'question',
text: i18n.tsx.voteConfirm({ choice: props.poll.choices[id].text }),
@ -145,7 +145,7 @@ const vote = async (id) => {
.done {
.choice {
cursor: default;
cursor: initial;
}
}
</style>

View File

@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</details>
<details v-if="note.poll">
<summary>{{ i18n.ts.poll }}</summary>
<MkPoll :noteId="note.id" :poll="note.poll"/>
<MkPoll :noteId="note.id" :poll="note.poll" :readOnly="inEmbedPage"/>
</details>
<button v-if="isLong && collapsed" :class="$style.fade" class="_button" @click="collapsed = false">
<span :class="$style.fadeLabel">{{ i18n.ts.showMore }}</span>
@ -30,7 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ref, inject } from 'vue';
import * as Misskey from 'misskey-js';
import MkMediaList from '@/components/MkMediaList.vue';
import MkPoll from '@/components/MkPoll.vue';
@ -44,6 +44,8 @@ const props = defineProps<{
const isLong = shouldCollapsed(props.note, []);
const inEmbedPage = inject<boolean>('EMBED_PAGE', false);
const collapsed = ref(isLong);
</script>

View File

@ -8,6 +8,7 @@ import * as Misskey from 'misskey-js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { miLocalStorage } from '@/local-storage.js';
import { DEFAULT_INFO_IMAGE_URL, DEFAULT_NOT_FOUND_IMAGE_URL, DEFAULT_SERVER_ERROR_IMAGE_URL } from '@/const.js';
import { embedPage } from '@/config.js';
// TODO: 他のタブと永続化されたstateを同期
@ -36,7 +37,7 @@ export const infoImageUrl = computed(() => instance.infoImageUrl ?? DEFAULT_INFO
export const notFoundImageUrl = computed(() => instance.notFoundImageUrl ?? DEFAULT_NOT_FOUND_IMAGE_URL);
export const isEnabledUrlPreview = computed(() => instance.enableUrlPreview ?? true);
export const isEnabledUrlPreview = computed(() => (instance.enableUrlPreview ?? true) && !embedPage);
export async function fetchInstance(force = false): Promise<Misskey.entities.MetaDetailed> {
if (!force) {

View File

@ -172,22 +172,11 @@ 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];
};
type PopupOptions = {
callEvenOnEmbedPage?: boolean;
};
export function popup<T extends Component>(
component: T,
props: ComponentProps<T>,
events: ComponentEmit<T> = {} as ComponentEmit<T>,
options: PopupOptions = {},
): { dispose: () => void } {
const _options = Object.assign({
callEvenOnEmbedPage: false,
}, options) as Required<PopupOptions>;
if (embedPage && !_options.callEvenOnEmbedPage) return { dispose: () => {} };
markRaw(component);
const id = ++popupIdCount;

View File

@ -3,10 +3,11 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { defineAsyncComponent } from 'vue';
import { defineAsyncComponent, inject } from 'vue';
import { $i } from '@/account.js';
import { i18n } from '@/i18n.js';
import { popup } from '@/os.js';
import { embedPage } from '@/config.js';
export type OpenOnRemoteOptions = {
/**
@ -47,6 +48,9 @@ export type OpenOnRemoteOptions = {
export function pleaseLogin(path?: string, openOnRemote?: OpenOnRemoteOptions) {
if ($i) return;
if (embedPage) {
window.open(path ?? '/', '_blank', 'noopener');
} else {
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
autoSet: true,
message: openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired,
@ -59,6 +63,7 @@ export function pleaseLogin(path?: string, openOnRemote?: OpenOnRemoteOptions) {
},
closed: () => dispose(),
});
}
throw new Error('signin required');
}