mirror of
https://git.boykissers.com/pawkey/pawkey-sk.git
synced 2025-12-20 04:04:16 +00:00
fix: fix stuff after merge
This commit is contained in:
@@ -7,13 +7,13 @@ import { defineAsyncComponent, reactive, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { apiUrl } from '@@/js/config.js';
|
||||
import type { MenuItem, MenuButton } from '@/types/menu.js';
|
||||
import { showSuspendedDialog } from '@/scripts/show-suspended-dialog.js';
|
||||
import { showSuspendedDialog } from '@/utility/show-suspended-dialog.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { del, get, set } from '@/scripts/idb-proxy.js';
|
||||
import { del, get, set } from '@/utility/idb-proxy.js';
|
||||
import { waiting, popup, popupMenu, success, alert } from '@/os.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { unisonReload, reloadChannel } from '@/scripts/unison-reload.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { unisonReload, reloadChannel } from '@/utility/unison-reload.js';
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ import { ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { instanceName } from '@@/js/config.js';
|
||||
import type { MenuItem } from '@/types/menu.js';
|
||||
import sanitizeHtml from '@/scripts/sanitize-html.js';
|
||||
import sanitizeHtml from '@/utility/sanitize-html.js';
|
||||
import XSigninDialog from '@/components/MkSigninDialog.vue';
|
||||
import XSignupDialog from '@/components/MkSignupDialog.vue';
|
||||
import PwVisitorMusic from '@/components/PwVisitorMusic.vue';
|
||||
|
||||
@@ -346,7 +346,7 @@ import { searchEngineMap } from '@/scripts/search-engine-map.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import * as os from '@/os.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { reloadAsk } from '@/scripts/reload-ask.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
|
||||
@@ -35,9 +35,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkRadios v-model="overridedDeviceKind">
|
||||
<template #label><SearchLabel>{{ i18n.ts.overridedDeviceKind }}</SearchLabel></template>
|
||||
<option :value="null">{{ i18n.ts.auto }}</option>
|
||||
<option value="smartphone"><i class="ti ti-device-mobile"/> {{ i18n.ts.smartphone }}</option>
|
||||
<option value="tablet"><i class="ti ti-device-tablet"/> {{ i18n.ts.tablet }}</option>
|
||||
<option value="desktop"><i class="ti ti-device-desktop"/> {{ i18n.ts.desktop }}</option>
|
||||
<option value="smartphone">{{ i18n.ts.smartphone }}</option>
|
||||
<option value="tablet">{{ i18n.ts.tablet }}</option>
|
||||
<option value="desktop">{{ i18n.ts.desktop }}</option>
|
||||
</MkRadios>
|
||||
</SearchMarker>
|
||||
|
||||
|
||||
@@ -4,199 +4,232 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="_spacer" :style="{ '--MI_SPACER-w': narrow ? '800px' : '1100px', ...background }">
|
||||
<div ref="rootEl" class="ftskorzw" :class="{ wide: !narrow }" style="container-type: inline-size;">
|
||||
<div class="main _gaps">
|
||||
<MkInfo v-if="user.isSuspended" :warn="true">{{ i18n.ts.userSuspended }}</MkInfo>
|
||||
<MkInfo v-if="user.isSilenced" :warn="true">{{ i18n.ts.userSilenced }}</MkInfo>
|
||||
<div class="_spacer" :style="{ '--MI_SPACER-w': narrow ? '800px' : '1100px', ...background }">
|
||||
<div ref="rootEl" class="ftskorzw" :class="{ wide: !narrow }" style="container-type: inline-size;">
|
||||
<div class="main _gaps">
|
||||
<MkInfo v-if="user.isSuspended" :warn="true">{{ i18n.ts.userSuspended }}</MkInfo>
|
||||
<MkInfo v-if="user.isSilenced" :warn="true">{{ i18n.ts.userSilenced }}</MkInfo>
|
||||
|
||||
<div class="profile _gaps">
|
||||
<MkAccountMoved v-if="user.movedTo" :movedTo="user.movedTo"/>
|
||||
<MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!"/>
|
||||
<MkInfo v-if="user.host == null && user.username.includes('.')">{{ i18n.ts.isSystemAccount }}</MkInfo>
|
||||
<div class="profile _gaps">
|
||||
<MkAccountMoved v-if="user.movedTo" :movedTo="user.movedTo" />
|
||||
<MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!" />
|
||||
<MkInfo v-if="user.host == null && user.username.includes('.')">{{ i18n.ts.isSystemAccount }}
|
||||
</MkInfo>
|
||||
|
||||
<div :key="user.id" class="main _panel">
|
||||
<div class="banner-container" :class="{ [$style.bannerContainerTall]: useTallBanner }">
|
||||
<div ref="bannerEl" class="banner" :style="style"></div>
|
||||
<div class="fade"></div>
|
||||
<div class="title">
|
||||
<MkUserName class="name" :user="user" :nowrap="true"/>
|
||||
<div class="bottom">
|
||||
<span class="username"><MkAcct :user="user" :detail="true"/></span>
|
||||
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
|
||||
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
|
||||
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
|
||||
<button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button" @click="showMemoTextarea">
|
||||
<i class="ti ti-edit"/> {{ i18n.ts.addMemo }}
|
||||
</button>
|
||||
<div :key="user.id" class="main _panel">
|
||||
<div class="banner-container" :class="{ [$style.bannerContainerTall]: useTallBanner }">
|
||||
<div ref="bannerEl" class="banner" :style="style"></div>
|
||||
<div class="fade"></div>
|
||||
<div class="title">
|
||||
<MkUserName class="name" :user="user" :nowrap="true" />
|
||||
<div class="bottom">
|
||||
<span class="username">
|
||||
<MkAcct :user="user" :detail="true" />
|
||||
</span>
|
||||
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin"
|
||||
style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
|
||||
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i
|
||||
class="ti ti-lock"></i></span>
|
||||
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
|
||||
<button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button"
|
||||
@click="showMemoTextarea">
|
||||
<i class="ti ti-edit" /> {{ i18n.ts.addMemo }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="$i && $i.id != user.id" :class="$style.infoBadges">
|
||||
<li v-if="user.isFollowed && user.isFollowing">{{ i18n.ts.mutuals }}</li>
|
||||
<li v-else-if="user.isFollowing">{{ i18n.ts.following }}</li>
|
||||
<li v-else-if="user.isFollowed">{{ i18n.ts.followsYou }}</li>
|
||||
<li v-if="user.isMuted">{{ i18n.ts.muted }}</li>
|
||||
<li v-if="user.isRenoteMuted">{{ i18n.ts.renoteMuted }}</li>
|
||||
<li v-if="user.isBlocking">{{ i18n.ts.blocked }}</li>
|
||||
<li v-if="user.isBlocked && $i.isModerator">{{ i18n.ts.blockingYou }}</li>
|
||||
</ul>
|
||||
<div :class="$style.actions" class="actions">
|
||||
<button :class="$style.actionsMenu" class="menu _button" @click="menu"><i
|
||||
class="ti ti-dots"></i></button>
|
||||
<MkFollowButton v-if="$i?.id != user.id" v-model:user="user"
|
||||
:class="$style.actionsFollow" :disabled="disableFollowControls" :inline="true"
|
||||
:transparent="false" :full="true" class="koudoku"
|
||||
@update:wait="onFollowButtonDisabledChanged" />
|
||||
<div v-if="hasFollowRequest" :class="$style.actionsBanner">{{
|
||||
i18n.ts.receiveFollowRequest }}</div>
|
||||
<MkButton v-if="hasFollowRequest" :class="$style.actionsAccept"
|
||||
:disabled="disableFollowControls" :inline="true" :transparent="false" :full="true"
|
||||
rounded primary @click="acceptFollowRequest"><i class="ti ti-check" /> {{
|
||||
i18n.ts.accept }}</MkButton>
|
||||
<MkButton v-if="hasFollowRequest" :class="$style.actionsReject"
|
||||
:disabled="disableFollowControls" :inline="true" :transparent="false" :full="true"
|
||||
rounded danger @click="rejectFollowRequest"><i class="ti ti-x" /> {{ i18n.ts.reject
|
||||
}}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="$i && $i.id != user.id" :class="$style.infoBadges">
|
||||
<li v-if="user.isFollowed && user.isFollowing">{{ i18n.ts.mutuals }}</li>
|
||||
<li v-else-if="user.isFollowing">{{ i18n.ts.following }}</li>
|
||||
<li v-else-if="user.isFollowed">{{ i18n.ts.followsYou }}</li>
|
||||
<li v-if="user.isMuted">{{ i18n.ts.muted }}</li>
|
||||
<li v-if="user.isRenoteMuted">{{ i18n.ts.renoteMuted }}</li>
|
||||
<li v-if="user.isBlocking">{{ i18n.ts.blocked }}</li>
|
||||
<li v-if="user.isBlocked && $i.isModerator">{{ i18n.ts.blockingYou }}</li>
|
||||
</ul>
|
||||
<div :class="$style.actions" class="actions">
|
||||
<button :class="$style.actionsMenu" class="menu _button" @click="menu"><i class="ti ti-dots"></i></button>
|
||||
<MkFollowButton v-if="$i?.id != user.id" v-model:user="user" :class="$style.actionsFollow" :disabled="disableFollowControls" :inline="true" :transparent="false" :full="true" class="koudoku" @update:wait="onFollowButtonDisabledChanged"/>
|
||||
<div v-if="hasFollowRequest" :class="$style.actionsBanner">{{ i18n.ts.receiveFollowRequest }}</div>
|
||||
<MkButton v-if="hasFollowRequest" :class="$style.actionsAccept" :disabled="disableFollowControls" :inline="true" :transparent="false" :full="true" rounded primary @click="acceptFollowRequest"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
|
||||
<MkButton v-if="hasFollowRequest" :class="$style.actionsReject" :disabled="disableFollowControls" :inline="true" :transparent="false" :full="true" rounded danger @click="rejectFollowRequest"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
|
||||
<MkAvatar class="avatar" :class="{ [$style.avatarTall]: useTallBanner }" :user="user"
|
||||
indicator />
|
||||
<div class="title">
|
||||
<MkUserName :user="user" :nowrap="false" class="name" />
|
||||
<div class="bottom">
|
||||
<span class="username">
|
||||
<MkAcct :user="user" :detail="true" />
|
||||
</span>
|
||||
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin"
|
||||
style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
|
||||
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
|
||||
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<MkAvatar class="avatar" :class="{ [$style.avatarTall]: useTallBanner }" :user="user" indicator/>
|
||||
<div class="title">
|
||||
<MkUserName :user="user" :nowrap="false" class="name"/>
|
||||
<div class="bottom">
|
||||
<span class="username"><MkAcct :user="user" :detail="true"/></span>
|
||||
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
|
||||
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
|
||||
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
|
||||
<div v-if="user.followedMessage != null" class="followedMessage">
|
||||
<MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin>
|
||||
<div class="messageHeader">{{ i18n.ts.messageToFollower }}</div>
|
||||
<div>
|
||||
<MkSparkle>
|
||||
<Mfm :plain="true" :text="user.followedMessage" :author="user"
|
||||
class="_selectable" />
|
||||
</MkSparkle>
|
||||
</div>
|
||||
</MkFukidashi>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="user.followedMessage != null" class="followedMessage">
|
||||
<MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin>
|
||||
<div class="messageHeader">{{ i18n.ts.messageToFollower }}</div>
|
||||
<div><MkSparkle><Mfm :plain="true" :text="user.followedMessage" :author="user" class="_selectable"/></MkSparkle></div>
|
||||
</MkFukidashi>
|
||||
</div>
|
||||
<div v-if="user.roles.length > 0" class="roles">
|
||||
<span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role" :style="{ '--color': role.color }">
|
||||
<MkA v-adaptive-bg :to="`/roles/${role.id}`">
|
||||
<img v-if="role.iconUrl" style="height: 1.3em; vertical-align: -22%;" :src="role.iconUrl"/>
|
||||
{{ role.name }}
|
||||
</MkA>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="iAmModerator" class="moderationNote">
|
||||
<MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manualSave>
|
||||
<template #label>{{ i18n.ts.moderationNote }}</template>
|
||||
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
|
||||
</MkTextarea>
|
||||
<div v-else>
|
||||
<MkButton small @click="editModerationNote = true">{{ i18n.ts.addModerationNote }}</MkButton>
|
||||
<div v-if="user.roles.length > 0" class="roles">
|
||||
<span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role"
|
||||
:style="{ '--color': role.color }">
|
||||
<MkA v-adaptive-bg :to="`/roles/${role.id}`">
|
||||
<img v-if="role.iconUrl" style="height: 1.3em; vertical-align: -22%;"
|
||||
:src="role.iconUrl" />
|
||||
{{ role.name }}
|
||||
</MkA>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}">
|
||||
<div class="heading" v-text="i18n.ts.memo"/>
|
||||
<textarea
|
||||
ref="memoTextareaEl"
|
||||
v-model="memoDraft"
|
||||
rows="1"
|
||||
@focus="isEditingMemo = true"
|
||||
@blur="updateMemo"
|
||||
@input="adjustMemoTextarea"
|
||||
/>
|
||||
</div>
|
||||
<div class="description">
|
||||
<MkOmit>
|
||||
<Mfm v-if="user.description" :text="user.description" :isBlock="true" :isNote="false" :author="user" class="_selectable"/>
|
||||
<div v-if="iAmModerator" class="moderationNote">
|
||||
<MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')"
|
||||
v-model="moderationNote" manualSave>
|
||||
<template #label>{{ i18n.ts.moderationNote }}</template>
|
||||
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
|
||||
</MkTextarea>
|
||||
<div v-else>
|
||||
<MkButton small @click="editModerationNote = true">{{ i18n.ts.addModerationNote }}
|
||||
</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isEditingMemo || memoDraft" class="memo" :class="{ 'no-memo': !memoDraft }">
|
||||
<div class="heading" v-text="i18n.ts.memo" />
|
||||
<textarea ref="memoTextareaEl" v-model="memoDraft" rows="1" @focus="isEditingMemo = true"
|
||||
@blur="updateMemo" @input="adjustMemoTextarea" />
|
||||
</div>
|
||||
<div class="description">
|
||||
<Mfm v-if="user.description" :text="user.description" :isBlock="true" :isNote="false"
|
||||
:author="user" class="_selectable" />
|
||||
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
|
||||
</MkOmit>
|
||||
</div>
|
||||
<div class="fields system">
|
||||
<dl v-if="user.location" class="field">
|
||||
<dt class="name"><i class="ti ti-map-pin ti-fw"></i> {{ i18n.ts.location }}</dt>
|
||||
<dd class="value">{{ user.location }}</dd>
|
||||
</dl>
|
||||
<dl v-if="user.birthday" class="field">
|
||||
<dt class="name"><i class="ti ti-cake ti-fw"></i> {{ i18n.ts.birthday }}</dt>
|
||||
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ i18n.tsx.yearsOld({ age }) }})</dd>
|
||||
</dl>
|
||||
<dl class="field">
|
||||
<dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt>
|
||||
<dd class="value">{{ dateString(user.createdAt) }} (<MkTime :time="user.createdAt"/>)</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div v-if="user.fields.length > 0" class="fields">
|
||||
<dl v-for="(field, i) in user.fields" :key="i" class="field">
|
||||
<dt class="name">
|
||||
<Mfm :text="field.name" :author="user" :plain="true" :colored="false" class="_selectable"/>
|
||||
</dt>
|
||||
<dd class="value">
|
||||
<Mfm :text="field.value" :author="user" :colored="false" class="_selectable"/>
|
||||
<i v-if="user.verifiedLinks.includes(field.value)" v-tooltip:dialog="i18n.ts.verifiedLink" class="ti ti-circle-check" :class="$style.verifiedLink"></i>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="status">
|
||||
<MkA :to="userPage(user)">
|
||||
<b>{{ number(user.notesCount) }}</b>
|
||||
<span>{{ i18n.ts.notes }}</span>
|
||||
</MkA>
|
||||
<MkA v-if="isFollowingVisibleForMe(user)" :to="userPage(user, 'following')">
|
||||
<b>{{ number(user.followingCount) }}</b>
|
||||
<span>{{ i18n.ts.following }}</span>
|
||||
</MkA>
|
||||
<MkA v-if="isFollowersVisibleForMe(user)" :to="userPage(user, 'followers')">
|
||||
<b>{{ number(user.followersCount) }}</b>
|
||||
<span>{{ i18n.ts.followers }}</span>
|
||||
</MkA>
|
||||
</div>
|
||||
<div class="fields system">
|
||||
<dl v-if="user.location" class="field">
|
||||
<dt class="name"><i class="ti ti-map-pin ti-fw"></i> {{ i18n.ts.location }}</dt>
|
||||
<dd class="value">{{ user.location }}</dd>
|
||||
</dl>
|
||||
<dl v-if="user.birthday" class="field">
|
||||
<dt class="name"><i class="ti ti-cake ti-fw"></i> {{ i18n.ts.birthday }}</dt>
|
||||
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{
|
||||
i18n.tsx.yearsOld({ age }) }})
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="field">
|
||||
<dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt>
|
||||
<dd class="value">{{ dateString(user.createdAt) }} (
|
||||
<MkTime :time="user.createdAt" />)
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div v-if="user.fields.length > 0" class="fields">
|
||||
<dl v-for="(field, i) in user.fields" :key="i" class="field">
|
||||
<dt class="name">
|
||||
<Mfm :text="field.name" :author="user" :plain="true" :colored="false"
|
||||
class="_selectable" />
|
||||
</dt>
|
||||
<dd class="value">
|
||||
<Mfm :text="field.value" :author="user" :colored="false" class="_selectable" />
|
||||
<i v-if="user.verifiedLinks.includes(field.value)"
|
||||
v-tooltip:dialog="i18n.ts.verifiedLink" class="ti ti-circle-check"
|
||||
:class="$style.verifiedLink"></i>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="status">
|
||||
<MkA :to="userPage(user)">
|
||||
<b>{{ number(user.notesCount) }}</b>
|
||||
<span>{{ i18n.ts.notes }}</span>
|
||||
</MkA>
|
||||
<MkA v-if="isFollowingVisibleForMe(user)" :to="userPage(user, 'following')">
|
||||
<b>{{ number(user.followingCount) }}</b>
|
||||
<span>{{ i18n.ts.following }}</span>
|
||||
</MkA>
|
||||
<MkA v-if="isFollowersVisibleForMe(user)" :to="userPage(user, 'followers')">
|
||||
<b>{{ number(user.followersCount) }}</b>
|
||||
<span>{{ i18n.ts.followers }}</span>
|
||||
</MkA>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="contents _gaps">
|
||||
<MkInfo v-if="user.pinnedNotes.length === 0 && $i?.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo>
|
||||
<template v-if="narrow">
|
||||
<MkLazy v-if="user.musicUrl">
|
||||
<XProfileMusic :key="user.id" :user="user"/>
|
||||
</MkLazy>
|
||||
<MkLazy>
|
||||
<XFiles :key="user.id" :user="user" :collapsed="true" @unfold="emit('unfoldFiles')"/>
|
||||
</MkLazy>
|
||||
<MkLazy>
|
||||
<XActivity :key="user.id" :user="user" :collapsed="true"/>
|
||||
</MkLazy>
|
||||
<MkLazy v-if="user.listenbrainz && listenbrainzdata">
|
||||
<XListenBrainz :key="user.id" :user="user" :collapsed="true"/>
|
||||
</MkLazy>
|
||||
</template>
|
||||
<!-- <div v-if="!disableNotes">
|
||||
<div class="contents _gaps">
|
||||
<MkInfo v-if="user.pinnedNotes.length === 0 && $i?.id === user.id">{{ i18n.ts.userPagePinTip }}
|
||||
</MkInfo>
|
||||
<template v-if="narrow">
|
||||
<MkLazy v-if="user.musicUrl">
|
||||
<XProfileMusic :key="user.id" :user="user" />
|
||||
</MkLazy>
|
||||
<MkLazy>
|
||||
<XFiles :key="user.id" :user="user" :collapsed="true" @unfold="emit('unfoldFiles')" />
|
||||
</MkLazy>
|
||||
<MkLazy>
|
||||
<XActivity :key="user.id" :user="user" :collapsed="true" />
|
||||
</MkLazy>
|
||||
<MkLazy v-if="user.listenbrainz && listenbrainzdata">
|
||||
<XListenBrainz :key="user.id" :user="user" :collapsed="true" />
|
||||
</MkLazy>
|
||||
</template>
|
||||
<!-- <div v-if="!disableNotes">
|
||||
<MkLazy>
|
||||
<XTimeline :user="user"/>
|
||||
</MkLazy>
|
||||
</div> -->
|
||||
<MkStickyContainer>
|
||||
<template #header>
|
||||
<!-- You can't use v-if on these, as MkTab first *deletes* and replaces all children with native HTML elements. -->
|
||||
<!-- Instead, we add a "no notes" placeholder and default to null (all notes) if there's nothing pinned. -->
|
||||
<!-- It also converts all comments into text! -->
|
||||
<MkTab v-model="noteview" :class="$style.tab">
|
||||
<option value="pinned">{{ i18n.ts.pinnedOnly }}</option>
|
||||
<option :value="null">{{ i18n.ts.notes }}</option>
|
||||
<option value="all">{{ i18n.ts.all }}</option>
|
||||
<option value="files">{{ i18n.ts.withFiles }}</option>
|
||||
</MkTab>
|
||||
</template>
|
||||
<MkLazy>
|
||||
<div v-if="noteview === 'pinned'" class="_gaps">
|
||||
<div v-if="user.pinnedNotes.length < 1" class="_fullinfo">
|
||||
<img :src="infoImageUrl" draggable="false" aria-hidden="true" :alt="i18n.ts.noNotes"/>
|
||||
<div>{{ i18n.ts.noNotes }}</div>
|
||||
<MkStickyContainer>
|
||||
<template #header>
|
||||
<!-- You can't use v-if on these, as MkTab first *deletes* and replaces all children with native HTML elements. -->
|
||||
<!-- Instead, we add a "no notes" placeholder and default to null (all notes) if there's nothing pinned. -->
|
||||
<!-- It also converts all comments into text! -->
|
||||
<MkTab v-model="noteview" :class="$style.tab">
|
||||
<option value="pinned">{{ i18n.ts.pinnedOnly }}</option>
|
||||
<option :value="null">{{ i18n.ts.notes }}</option>
|
||||
<option value="all">{{ i18n.ts.all }}</option>
|
||||
<option value="files">{{ i18n.ts.withFiles }}</option>
|
||||
</MkTab>
|
||||
</template>
|
||||
<MkLazy>
|
||||
<div v-if="noteview === 'pinned'" class="_gaps">
|
||||
<div v-if="user.pinnedNotes.length < 1" class="_fullinfo">
|
||||
<img :src="infoImageUrl" draggable="false" aria-hidden="true"
|
||||
:alt="i18n.ts.noNotes" />
|
||||
<div>{{ i18n.ts.noNotes }}</div>
|
||||
</div>
|
||||
<div v-else class="_panel">
|
||||
<DynamicNote v-for="note of user.pinnedNotes" :key="note.id" class="note"
|
||||
:class="$style.pinnedNote" :note="note" :pinned="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="_panel">
|
||||
<DynamicNote v-for="note of user.pinnedNotes" :key="note.id" class="note" :class="$style.pinnedNote" :note="note" :pinned="true"/>
|
||||
</div>
|
||||
</div>
|
||||
<MkNotes v-else :class="$style.tl" :noGap="true" :pagination="AllPagination"/>
|
||||
</MkLazy>
|
||||
</MkStickyContainer>
|
||||
<MkNotes v-else :class="$style.tl" :noGap="true" :pagination="AllPagination" />
|
||||
</MkLazy>
|
||||
</MkStickyContainer>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;">
|
||||
<XFiles :key="user.id" :user="user" @unfold="emit('unfoldFiles')" />
|
||||
<XActivity :key="user.id" :user="user" />
|
||||
<XListenBrainz v-if="user.listenbrainz && listenbrainzdata" :key="user.id" :user="user" />
|
||||
<XProfileMusic v-if="user.musicUrl" :key="user.id" :user="user" :collapsed="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;">
|
||||
<XFiles :key="user.id" :user="user" @unfold="emit('unfoldFiles')"/>
|
||||
<XActivity :key="user.id" :user="user"/>
|
||||
<XListenBrainz v-if="user.listenbrainz && listenbrainzdata" :key="user.id" :user="user"/>
|
||||
<XProfileMusic v-if="user.musicUrl" :key="user.id" :user="user" :collapsed="true"/>
|
||||
</div>
|
||||
<div class="background"></div>
|
||||
</div>
|
||||
<div class="background"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -277,7 +310,7 @@ const noteview = ref<string | null>(props.user.pinnedNotes.length ? 'pinned' : n
|
||||
|
||||
const listenbrainzdata = ref(false);
|
||||
if (props.user.listenbrainz) {
|
||||
(async function() {
|
||||
(async function () {
|
||||
try {
|
||||
const response = await window.fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, {
|
||||
method: 'GET',
|
||||
@@ -336,11 +369,11 @@ const style = computed(() => {
|
||||
if (props.user.bannerUrl == null) return {};
|
||||
if (prefer.s.disableShowingAnimatedImages) {
|
||||
return {
|
||||
backgroundImage: `url(${ getStaticImageUrl(props.user.bannerUrl) })`,
|
||||
backgroundImage: `url(${getStaticImageUrl(props.user.bannerUrl)})`,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
backgroundImage: `url(${ props.user.bannerUrl })`,
|
||||
backgroundImage: `url(${props.user.bannerUrl})`,
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -461,7 +494,7 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.background{
|
||||
.background {
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
background: var(--backgroundImageStatic);
|
||||
@@ -479,28 +512,28 @@ onUnmounted(() => {
|
||||
|
||||
.ftskorzw {
|
||||
|
||||
> .main {
|
||||
>.main {
|
||||
|
||||
> .punished {
|
||||
>.punished {
|
||||
font-size: 0.8em;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
> .profile {
|
||||
>.profile {
|
||||
|
||||
> .main {
|
||||
>.main {
|
||||
position: relative;
|
||||
overflow: clip;
|
||||
background: color-mix(in srgb, var(--MI_THEME-panel) 65%, transparent);
|
||||
|
||||
> .banner-container {
|
||||
>.banner-container {
|
||||
position: relative;
|
||||
height: 250px;
|
||||
overflow: clip;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
> .banner {
|
||||
>.banner {
|
||||
height: 100%;
|
||||
background-color: #4c5e6d;
|
||||
background-size: cover;
|
||||
@@ -509,7 +542,7 @@ onUnmounted(() => {
|
||||
will-change: background-position;
|
||||
}
|
||||
|
||||
> .fade {
|
||||
>.fade {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@@ -518,7 +551,7 @@ onUnmounted(() => {
|
||||
background: linear-gradient(transparent, rgba(#000, 0.7));
|
||||
}
|
||||
|
||||
> .actions {
|
||||
>.actions {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
@@ -528,7 +561,7 @@ onUnmounted(() => {
|
||||
padding: 8px;
|
||||
border-radius: var(--MI-radius-lg);
|
||||
|
||||
> .menu {
|
||||
>.menu {
|
||||
vertical-align: bottom;
|
||||
height: 31px;
|
||||
width: 31px;
|
||||
@@ -537,13 +570,13 @@ onUnmounted(() => {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
> .koudoku {
|
||||
>.koudoku {
|
||||
margin-left: 4px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
> .title {
|
||||
>.title {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@@ -552,7 +585,7 @@ onUnmounted(() => {
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
|
||||
> .name {
|
||||
>.name {
|
||||
display: block;
|
||||
margin: -10px;
|
||||
padding: 10px;
|
||||
@@ -562,8 +595,8 @@ onUnmounted(() => {
|
||||
filter: drop-shadow(0 0 4px #000);
|
||||
}
|
||||
|
||||
> .bottom {
|
||||
> * {
|
||||
>.bottom {
|
||||
>* {
|
||||
display: inline-block;
|
||||
margin-right: 16px;
|
||||
line-height: 20px;
|
||||
@@ -574,7 +607,7 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .add-note-button {
|
||||
>.add-note-button {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
color: #fff;
|
||||
-webkit-backdrop-filter: var(--MI-blur, blur(8px));
|
||||
@@ -587,15 +620,15 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .title {
|
||||
>.title {
|
||||
display: none;
|
||||
text-align: center;
|
||||
padding: 50px 8px 16px 8px;
|
||||
font-weight: bold;
|
||||
border-bottom: solid 0.5px var(--MI_THEME-divider);
|
||||
|
||||
> .bottom {
|
||||
> * {
|
||||
>.bottom {
|
||||
>* {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
opacity: 0.8;
|
||||
@@ -603,7 +636,7 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .avatar {
|
||||
>.avatar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 170px;
|
||||
@@ -614,10 +647,10 @@ onUnmounted(() => {
|
||||
filter: drop-shadow(1px 1px 3px rgba(#000, 0.2));
|
||||
}
|
||||
|
||||
> .followedMessage {
|
||||
>.followedMessage {
|
||||
padding: 24px 24px 0 154px;
|
||||
|
||||
> .fukidashi {
|
||||
>.fukidashi {
|
||||
display: block;
|
||||
--fukidashi-bg: color-mix(in srgb, var(--MI_THEME-accent), var(--MI_THEME-panel) 85%);
|
||||
--fukidashi-radius: 16px;
|
||||
@@ -630,14 +663,14 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .roles {
|
||||
>.roles {
|
||||
padding: 24px 24px 0 154px;
|
||||
font-size: 0.95em;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
> .role {
|
||||
>.role {
|
||||
border: solid 1px var(--color, var(--MI_THEME-divider));
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
margin-right: 4px;
|
||||
@@ -645,11 +678,11 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .moderationNote {
|
||||
>.moderationNote {
|
||||
margin: 12px 24px 0 154px;
|
||||
}
|
||||
|
||||
> .memo {
|
||||
>.memo {
|
||||
margin: 12px 24px 0 154px;
|
||||
background: transparent;
|
||||
color: var(--MI_THEME-fg);
|
||||
@@ -658,7 +691,7 @@ onUnmounted(() => {
|
||||
padding: 8px;
|
||||
line-height: 0;
|
||||
|
||||
> .heading {
|
||||
>.heading {
|
||||
text-align: left;
|
||||
color: color(from var(--MI_THEME-fg) srgb r g b / 0.5);
|
||||
line-height: 1.5;
|
||||
@@ -682,22 +715,22 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .description {
|
||||
>.description {
|
||||
padding: 24px 24px 24px 154px;
|
||||
font-size: 0.95em;
|
||||
|
||||
> .empty {
|
||||
>.empty {
|
||||
margin: 0;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
> .fields {
|
||||
>.fields {
|
||||
padding: 24px;
|
||||
font-size: 0.9em;
|
||||
border-top: solid 0.5px var(--MI_THEME-divider);
|
||||
|
||||
> .field {
|
||||
>.field {
|
||||
display: flex;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@@ -707,7 +740,7 @@ onUnmounted(() => {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
> .name {
|
||||
>.name {
|
||||
width: 30%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
@@ -716,7 +749,7 @@ onUnmounted(() => {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
> .value {
|
||||
>.value {
|
||||
width: 70%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
@@ -725,16 +758,15 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
&.system > .field > .name {
|
||||
}
|
||||
&.system>.field>.name {}
|
||||
}
|
||||
|
||||
> .status {
|
||||
>.status {
|
||||
display: flex;
|
||||
padding: 24px;
|
||||
border-top: solid 0.5px var(--MI_THEME-divider);
|
||||
|
||||
> a {
|
||||
>a {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
|
||||
@@ -746,12 +778,12 @@ onUnmounted(() => {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
> b {
|
||||
>b {
|
||||
display: block;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
> span {
|
||||
>span {
|
||||
font-size: 70%;
|
||||
}
|
||||
}
|
||||
@@ -759,8 +791,8 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
> .contents {
|
||||
> .content {
|
||||
>.contents {
|
||||
>.content {
|
||||
margin-bottom: var(--MI-margin);
|
||||
}
|
||||
}
|
||||
@@ -770,12 +802,12 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
> .main {
|
||||
>.main {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
> .sub {
|
||||
>.sub {
|
||||
max-width: 350px;
|
||||
min-width: 350px;
|
||||
margin-left: var(--MI-margin);
|
||||
@@ -785,25 +817,25 @@ onUnmounted(() => {
|
||||
|
||||
@container (max-width: 500px) {
|
||||
.ftskorzw {
|
||||
> .main {
|
||||
> .profile > .main {
|
||||
> .banner-container {
|
||||
>.main {
|
||||
>.profile>.main {
|
||||
>.banner-container {
|
||||
height: 140px;
|
||||
|
||||
> .fade {
|
||||
>.fade {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> .title {
|
||||
>.title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
> .title {
|
||||
>.title {
|
||||
display: block;
|
||||
}
|
||||
|
||||
> .avatar {
|
||||
>.avatar {
|
||||
top: 90px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
@@ -812,39 +844,39 @@ onUnmounted(() => {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
> .followedMessage {
|
||||
>.followedMessage {
|
||||
padding: 16px 16px 0 16px;
|
||||
}
|
||||
|
||||
> .roles {
|
||||
>.roles {
|
||||
padding: 16px 16px 0 16px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
> .moderationNote {
|
||||
>.moderationNote {
|
||||
margin: 16px 16px 0 16px;
|
||||
}
|
||||
|
||||
> .memo {
|
||||
>.memo {
|
||||
margin: 16px 16px 0 16px;
|
||||
}
|
||||
|
||||
> .description {
|
||||
>.description {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
> .fields {
|
||||
>.fields {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
> .status {
|
||||
>.status {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
> .contents {
|
||||
> .nav {
|
||||
>.contents {
|
||||
>.nav {
|
||||
font-size: 80%;
|
||||
}
|
||||
}
|
||||
@@ -868,7 +900,7 @@ onUnmounted(() => {
|
||||
backdrop-filter: var(--MI-blur, blur(15px));
|
||||
border-radius: var(--MI-radius-sm);
|
||||
|
||||
> button {
|
||||
>button {
|
||||
border-radius: var(--MI-radius-sm);
|
||||
margin-left: 0.4rem;
|
||||
margin-right: 0.4rem;
|
||||
@@ -891,7 +923,7 @@ onUnmounted(() => {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
> * {
|
||||
>* {
|
||||
padding: 4px 8px;
|
||||
color: #fff;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
|
||||
@@ -4,9 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="meta" :class="$style.root">
|
||||
<MkFeaturedPhotos :class="$style.bg"/>
|
||||
<XTimeline v-if="meta.policies.ltlAvailable" :class="$style.tl"/>
|
||||
<div v-if="meta" class="rsqzvsbo">
|
||||
<MkFeaturedPhotos class="bg"/>
|
||||
<div class="logo-wrapper">
|
||||
<!-- <div class="powered-by">Powered by</div> -->
|
||||
<img :src="misskeysvg" class="misskey"/>
|
||||
@@ -37,7 +36,7 @@ import { ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkFeaturedPhotos from '@/components/MkFeaturedPhotos.vue';
|
||||
import misskeysvg from '/client-assets/pawkey.png';
|
||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||
import { misskeyApiGet } from '@/utility/misskey-api.js';
|
||||
import MkVisitorDashboard from '@/components/MkVisitorDashboard.vue';
|
||||
import { getProxiedImageUrl } from '@/utility/media-proxy.js';
|
||||
import { instance as meta } from '@/instance.js';
|
||||
@@ -61,61 +60,68 @@ misskeyApiGet('federation/instances', {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
height: 100cqh;
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
<style lang="scss" scoped>
|
||||
.rsqzvsbo {
|
||||
> .bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.tl {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 64px;
|
||||
margin: auto;
|
||||
padding: 128px 0;
|
||||
width: 500px;
|
||||
height: calc(100% - 256px);
|
||||
overflow: hidden;
|
||||
-webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
|
||||
mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
|
||||
> .tl {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 64px;
|
||||
margin: auto;
|
||||
padding: 128px 0;
|
||||
width: 500px;
|
||||
height: calc(100% - 256px);
|
||||
overflow: hidden;
|
||||
-webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
|
||||
mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.logoWrapper {
|
||||
position: fixed;
|
||||
top: 36px;
|
||||
left: 36px;
|
||||
flex: auto;
|
||||
color: #fff;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
> .logo-wrapper {
|
||||
position: fixed;
|
||||
top: 36px;
|
||||
left: 36px;
|
||||
flex: auto;
|
||||
color: #fff;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
|
||||
.poweredBy {
|
||||
color: var(--MI_THEME-fgOnAccent);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
> .powered-by {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.misskey {
|
||||
width: 120px;
|
||||
|
||||
@media (max-width: 450px) {
|
||||
width: 100px;
|
||||
> .misskey {
|
||||
width: 140px;
|
||||
@media (max-width: 450px) {
|
||||
width: 130px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .emojis {
|
||||
position: fixed;
|
||||
bottom: 32px;
|
||||
left: 35px;
|
||||
|
||||
> * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .contents {
|
||||
position: relative;
|
||||
@@ -123,30 +129,33 @@ misskeyApiGet('federation/instances', {
|
||||
margin: auto;
|
||||
padding: 100px 0 100px 0;
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
@media (max-width: 1200px) {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
> .federation {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
background: var(--MI_THEME-acrylicPanel);
|
||||
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
|
||||
backdrop-filter: var(--MI-blur, blur(15px));
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
overflow: clip;
|
||||
width: 800px;
|
||||
padding: 8px 0;
|
||||
|
||||
@media (max-width: 900px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
.federation {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
background: color(from var(--MI_THEME-panel) srgb r g b / 0.5);
|
||||
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
|
||||
backdrop-filter: var(--MI-blur, blur(15px));
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
overflow: clip;
|
||||
width: 800px;
|
||||
padding: 8px 0;
|
||||
|
||||
@media (max-width: 900px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
<style lang="scss" module>
|
||||
.federationInstance {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -155,13 +164,13 @@ misskeyApiGet('federation/instances', {
|
||||
margin: 0 10px 0 0;
|
||||
background: var(--MI_THEME-panel);
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
}
|
||||
|
||||
.federationInstanceIcon {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
> :global(.icon) {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -420,7 +420,7 @@ function getPointerEvents() {
|
||||
|
||||
#devTicker {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
z-index: 2147483647;
|
||||
border-radius: 10px;
|
||||
|
||||
@@ -83,10 +83,6 @@ const isVideo = computed(() => {
|
||||
const url = instance.backgroundImageUrl.toLowerCase();
|
||||
return url.endsWith('.mp4') || url.endsWith('.webm') || url.endsWith('.ogg');
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
showMenu: showMenu,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -137,6 +133,11 @@ defineExpose({
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.homeButton {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
@@ -159,119 +160,117 @@ defineExpose({
|
||||
z-index: 1;
|
||||
overflow-y: scroll;
|
||||
background: var(--MI_THEME-accent);
|
||||
|
||||
>.banner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
-webkit-mask-image: linear-gradient(rgba(0, 0, 0, 1.0), transparent);
|
||||
mask-image: linear-gradient(rgba(0, 0, 0, 1.0), transparent);
|
||||
|
||||
> video {
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
> .image {
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
}
|
||||
|
||||
>.dashboard {
|
||||
position: relative;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
>.banner {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
-webkit-mask-image: linear-gradient(rgba(0, 0, 0, 1.0), transparent);
|
||||
mask-image: linear-gradient(rgba(0, 0, 0, 1.0), transparent);
|
||||
.main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
> video {
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
> .image {
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
}
|
||||
|
||||
>.dashboard {
|
||||
position: relative;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
>.main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
>.header {
|
||||
background: var(--MI_THEME-panel);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
>.wide {
|
||||
line-height: 50px;
|
||||
padding: 0 16px;
|
||||
|
||||
>.link {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
|
||||
>.narrow {
|
||||
>.menu {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
>.menu-back {
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
>.menu {
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 240px;
|
||||
height: 100vh;
|
||||
>.header {
|
||||
background: var(--MI_THEME-panel);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
>.link {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
>.wide {
|
||||
line-height: 50px;
|
||||
padding: 0 16px;
|
||||
|
||||
>.icon {
|
||||
margin-right: 1em;
|
||||
>.link {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
|
||||
>.divider {
|
||||
margin: 8px auto;
|
||||
width: calc(100% - 32px);
|
||||
border-top: solid 0.5px var(--MI_THEME-divider);
|
||||
>.narrow {
|
||||
>.menu {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
>.action {
|
||||
padding: 16px;
|
||||
.menu-back {
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
>button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
.menu {
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 240px;
|
||||
height: 100vh;
|
||||
background: var(--MI_THEME-panel);
|
||||
|
||||
&._button {
|
||||
background: var(--MI_THEME-panel);
|
||||
}
|
||||
>.link {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
|
||||
&:first-child {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
>.icon {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
>.divider {
|
||||
margin: 8px auto;
|
||||
width: calc(100% - 32px);
|
||||
border-top: solid 0.5px var(--MI_THEME-divider);
|
||||
}
|
||||
|
||||
>.action {
|
||||
padding: 16px;
|
||||
|
||||
> button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
border-radius: var(--MI-radius-ellipse);
|
||||
|
||||
&._button {
|
||||
background: var(--MI_THEME-panel);
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
packages/frontend/src/utility/sanitze-html.ts
Normal file
19
packages/frontend/src/utility/sanitze-html.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: dakkar and other Sharkey contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import original from 'sanitize-html';
|
||||
|
||||
export default function sanitizeHtml(str: string | null): string | null {
|
||||
if (str == null) return str;
|
||||
return original(str, {
|
||||
allowedTags: original.defaults.allowedTags.concat(['img', 'audio', 'video', 'center', 'details', 'summary']),
|
||||
allowedAttributes: {
|
||||
...original.defaults.allowedAttributes,
|
||||
a: original.defaults.allowedAttributes.a.concat(['style']),
|
||||
img: original.defaults.allowedAttributes.img.concat(['style']),
|
||||
'*': (original.defaults.allowedAttributes['*'] || []).concat(['style']),
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user