Compare commits

..

2 Commits

Author SHA1 Message Date
Natty b50249da02
Frontend: Changed powered by to "Magnetar"
ci/woodpecker/push/ociImagePush Pipeline was successful Details
2023-12-28 00:35:10 +01:00
Natty 7fbcc4ec19
Frontend: Removed dependence on Calckey note resolving and avatars 2023-12-28 00:34:52 +01:00
60 changed files with 263 additions and 228 deletions

View File

@ -20,7 +20,7 @@ magnetar-dev.local {
}
@render_html {
not path /api* /proxy* /files* /avatar* /identicon* /streaming
not path /api* /proxy* /files* /avatar* /identicon*
header Accept text/html*
}

View File

@ -853,7 +853,6 @@ export type Endpoints = {
};
res: Note[];
};
"notes/polls/recommendation": { req: TODO; res: TODO };
"notes/polls/vote": {
req: { noteId: Note["id"]; choice: number };
res: null;
@ -887,7 +886,6 @@ export type Endpoints = {
};
"notes/search-by-tag": { req: TODO; res: TODO };
"notes/search": { req: TODO; res: TODO };
"notes/show": { req: { noteId: Note["id"] }; res: Note };
"notes/state": { req: TODO; res: TODO };
"notes/timeline": {
req: {

View File

@ -3,13 +3,12 @@ import * as misskey from "calckey-js";
import { i18n } from "./i18n";
import { del, get, set } from "@/scripts/idb-proxy";
import { apiUrl } from "@/config";
import { waiting, api, popup, popupMenu, success, alert } from "@/os";
import { unisonReload, reloadChannel } from "@/scripts/unison-reload";
import { alert, api, popup, popupMenu, success, waiting } from "@/os";
import { reloadChannel, unisonReload } from "@/scripts/unison-reload";
// TODO: 他のタブと永続化されたstateを同期
type Account = misskey.entities.MeDetailed;
const accountData = localStorage.getItem("account");
// TODO: 外部からはreadonlyに

View File

@ -1,7 +1,7 @@
<template>
<div class="defgtij">
<div v-for="user in users" :key="user.id" class="avatar-holder">
<MkAvatar :user="user" class="avatar" />
<MagAvatar :user="user" class="avatar" />
</div>
</div>
</template>
@ -9,7 +9,7 @@
<script lang="ts" setup>
import { onMounted, ref, watch } from "vue";
import * as os from "@/os";
import { packed, endpoints } from "magnetar-common";
import { endpoints, packed } from "magnetar-common";
const props = defineProps<{
userIds: string[];

View File

@ -71,7 +71,7 @@
</div>
</div>
<div v-if="collapsedReply && appearNote.parent_note" class="info">
<MkAvatar class="avatar" :user="appearNote.parent_note.user" />
<MagAvatar class="avatar" :user="appearNote.parent_note.user" />
<MkUserName
class="username"
:user="appearNote.parent_note.user"
@ -95,7 +95,7 @@
>
<div class="main">
<div class="header-container">
<MkAvatar class="avatar" :user="appearNote.user" />
<MagAvatar class="avatar" :user="appearNote.user" />
<XNoteHeader class="header" :note="appearNote" />
</div>
<div class="body">

View File

@ -117,7 +117,7 @@
{{ item.description }}
</div>
<div class="user">
<MkAvatar
<MagAvatarResolvingProxy
:user="item.user"
class="avatar"
:show-indicator="true"

View File

@ -1,6 +1,6 @@
<template>
<div v-size="{ min: [350, 500] }" class="yohlumlk">
<MkAvatar class="avatar" :user="note.user" />
<MagAvatar class="avatar" :user="note.user" />
<div class="main">
<XNoteHeader class="header" :note="note" :mini="true" />
<div class="body">

View File

@ -20,7 +20,7 @@
:style="{ cursor: expandOnNoteClick ? 'pointer' : '' }"
>
<div class="avatar-container">
<MkAvatar class="avatar" :user="appearNote.user" />
<MagAvatar class="avatar" :user="appearNote.user" />
<div
v-if="!conversation || replies.length > 0"
class="line"

View File

@ -60,13 +60,13 @@
</template>
<script lang="ts" setup>
import { computed, ref } from "vue";
import { computed, ref, toRaw } from "vue";
import { sum } from "@/scripts/array";
import { pleaseLogin } from "@/scripts/please-login";
import * as os from "@/os";
import { i18n } from "@/i18n";
import { useInterval } from "@/scripts/use-interval";
import { packed } from "magnetar-common";
import { endpoints, packed } from "magnetar-common";
const props = defineProps<{
note: packed.PackNoteMaybeFull & { poll: {} };
@ -133,17 +133,14 @@ async function refresh() {
os.api("ap/show", { uri: props.note.uri })
.then((obj) => {
if (obj && obj.type === "Note" && obj.object.poll) {
props.note.poll = {
...props.note.poll,
expires_at: obj.object.poll.expiresAt,
multiple_choice: obj.object.poll.multiple,
options: obj.object.poll.choices?.map((c) => ({
title: c.text,
votes_count: c.votes,
voted: c.isVoted,
})),
};
if (obj && obj.type === "Note") {
os.magApi(
endpoints.GetNoteById,
{ attachments: true },
{ id: obj.object.id }
).then((n) => {
props.note.poll = { ...toRaw(props.note.poll), ...n.poll };
});
}
})
.catch((err) => {

View File

@ -42,7 +42,7 @@
{{ i18n.ts.followRequestYou }}
</span>
</div>
<MkAvatar
<MagAvatar
class="avatar"
:user="user"
:disable-preview="true"

View File

@ -6,7 +6,7 @@
class="info"
:to="`/user-info/${report.targetUserId}`"
>
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="report.targetUser"
:show-indicator="true"
@ -68,7 +68,6 @@
import MkButton from "@/components/MkButton.vue";
import MkSwitch from "@/components/form/switch.vue";
import MkKeyValue from "@/components/MkKeyValue.vue";
import { acct, userPage } from "@/filters/user";
import * as os from "@/os";
import { i18n } from "@/i18n";

View File

@ -8,7 +8,12 @@ export default defineComponent({
props: {
items: {
type: Array as PropType<
{ id: string; createdAt: string; _shouldInsertAd_: boolean }[]
{
id: string;
createdAt?: string;
created_at?: string;
_shouldInsertAd_: boolean;
}[]
>,
required: true,
},
@ -57,8 +62,11 @@ export default defineComponent({
if (
i !== props.items.length - 1 &&
new Date(item.createdAt).getDate() !==
new Date(props.items[i + 1].createdAt).getDate()
new Date(item.createdAt || item.created_at!).getDate() !==
new Date(
props.items[i + 1].createdAt ||
props.items[i + 1].created_at!
).getDate()
) {
const separator = h(
"div",
@ -76,10 +84,15 @@ export default defineComponent({
h("i", {
class: "ph-caret-up ph-bold ph-lg icon",
}),
getDateText(item.createdAt),
getDateText(
item.createdAt || item.created_at!
),
]),
h("span", [
getDateText(props.items[i + 1].createdAt),
getDateText(
props.items[i + 1].createdAt ||
props.items[i + 1].created_at!
),
h("i", {
class: "ph-caret-down ph-bold ph-lg icon",
}),

View File

@ -9,7 +9,7 @@
</div>
<article>
<header>
<MkAvatar :user="post.user" class="avatar" />
<MagAvatarResolvingProxy :user="post.user" class="avatar" />
</header>
<footer>
<span class="title">{{ post.title }}</span>
@ -19,8 +19,6 @@
</template>
<script lang="ts" setup>
import {} from "vue";
import { userName } from "@/filters/user";
import ImgWithBlurhash from "@/components/MkImgWithBlurhash.vue";
const props = defineProps<{

View File

@ -43,7 +43,7 @@
class="ph-fw ph-lg"
:class="item.icon"
></i>
<MkAvatar
<MagAvatarResolvingProxy
v-if="item.avatar"
:user="item.avatar"
class="avatar"
@ -87,7 +87,7 @@
@mouseenter.passive="onItemMouseEnter(item)"
@mouseleave.passive="onItemMouseLeave(item)"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="item.user"
class="avatar"
disableLink
@ -149,7 +149,7 @@
class="ph-fw ph-lg"
:class="item.icon"
></i>
<MkAvatar
<MagAvatarResolvingProxy
v-if="item.avatar"
:user="item.avatar"
class="avatar"
@ -184,20 +184,14 @@
<script lang="ts" setup>
import {
computed,
menu,
defineAsyncComponent,
nextTick,
onBeforeUnmount,
onMounted,
onUnmounted,
Ref,
ref,
watch,
} from "vue";
import { focusPrev, focusNext } from "@/scripts/focus";
import FormSwitch from "@/components/form/switch.vue";
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from "@/types/menu";
import { InnerMenuItem, MenuAction, MenuItem, MenuPending } from "@/types/menu";
import * as os from "@/os";
import { i18n } from "@/i18n";
import { FocusTrap } from "focus-trap-vue";

View File

@ -1,6 +1,6 @@
<template>
<div v-size="{ min: [350, 500] }" class="fefdfafb">
<MkAvatar class="avatar" :user="$i" disableLink />
<MagAvatarResolvingProxy class="avatar" :user="$i" disableLink />
<div class="main">
<div class="header">
<MkUserName :user="$i" />
@ -22,6 +22,7 @@
<script lang="ts" setup>
import { preprocess } from "@/scripts/preprocess";
import { $i } from "@/account";
const props = defineProps<{
text: string;

View File

@ -26,7 +26,7 @@
<XNoteResolvingProxy
:key="note._featuredId_ || note._prId_ || note.id"
class="qtqtichx"
:note="note.id"
:note="noteIsMag(note) ? note : note.id"
/>
</XList>
</div>
@ -41,6 +41,7 @@ import MkPagination from "@/components/MkPagination.vue";
import XNoteResolvingProxy from "@/components/MagNoteResolvingProxy.vue";
import XList from "@/components/MkDateSeparatedList.vue";
import { i18n } from "@/i18n";
import { noteIsMag } from "@/scripts-mag/mag-util";
const props = defineProps<{
pagination: Paging;

View File

@ -6,12 +6,12 @@
:class="notification.type"
>
<div class="head">
<MkAvatar
<MagAvatarResolvingProxy
v-if="notification.type === 'pollEnded'"
class="icon"
:user="notification.note.user"
/>
<MkAvatar
<MagAvatarResolvingProxy
v-else-if="notification.user"
class="icon"
:user="notification.user"
@ -187,7 +187,7 @@
:text="getNoteSummary(notification.note)"
:plain="true"
:nowrap="!full"
:custom-emojis="notification.note.emojis"
:custom-emojis="notification.note?.emojis"
/>
<i class="ph-quotes ph-fill ph-lg"></i>
</MkA>

View File

@ -20,7 +20,10 @@
class="account _button"
@click="openAccountMenu"
>
<MkAvatar :user="postAccount ?? $i" class="avatar" />
<MagAvatarResolvingProxy
:user="postAccount ?? $i"
class="avatar"
/>
</button>
<div class="right">
<span

View File

@ -25,8 +25,8 @@ import MkPostForm from "@/components/MkPostForm.vue";
import { packed } from "magnetar-common";
const props = defineProps<{
reply?: packed.PackNoteMaybeFull | misskey.entities.Note;
renote?: packed.PackNoteMaybeFull | misskey.entities.Note;
reply?: packed.PackNoteMaybeFull;
renote?: packed.PackNoteMaybeFull;
mention?: misskey.entities.User;
specified?: misskey.entities.User;
initialText?: string;
@ -34,7 +34,7 @@ const props = defineProps<{
initialFiles?: misskey.entities.DriveFile[];
initialLocalOnly?: boolean;
initialVisibleUsers?: misskey.entities.User[];
initialNote?: packed.PackNoteMaybeFull | misskey.entities.Note;
initialNote?: packed.PackNoteMaybeFull;
instant?: boolean;
fixed?: boolean;
autofocus?: boolean;

View File

@ -21,7 +21,7 @@
</div>
<div class="users">
<div v-for="u in users" :key="u.id" class="user">
<MkAvatar class="avatar" :user="u" />
<MagAvatarResolvingProxy class="avatar" :user="u" />
<MkUserName class="name" :user="u" :nowrap="true" />
</div>
<div v-if="users.length > 10" class="omitted">
@ -33,7 +33,6 @@
</template>
<script lang="ts" setup>
import {} from "vue";
import MkTooltip from "./MkTooltip.vue";
import { magIsUnicodeEmoji, magReactionToLegacy } from "@/scripts-mag/mag-util";
import { types } from "magnetar-common";

View File

@ -18,7 +18,7 @@
</template>
<script lang="ts" setup>
import { ref, computed, provide, onUnmounted } from "vue";
import { onUnmounted } from "vue";
import XNotes from "@/components/MkNotes.vue";
import MkInfo from "@/components/MkInfo.vue";
import * as os from "@/os";
@ -27,6 +27,7 @@ import * as sound from "@/scripts/sound";
import { $i } from "@/account";
import { i18n } from "@/i18n";
import { defaultStore } from "@/store";
import { endpoints } from "magnetar-common";
const props = defineProps<{
src: string;
@ -42,14 +43,22 @@ const emit = defineEmits<{
const tlComponent: InstanceType<typeof XNotes> = $ref();
const prepend = (note) => {
tlComponent.pagingComponent?.prepend(note);
const prepend = (note: string) => {
os.magApi(
endpoints.GetNoteById,
{ context: true, attachments: true },
{
id: note,
}
).then((n) => {
tlComponent.pagingComponent?.prepend(n);
emit("note");
emit("note");
if (props.sound) {
sound.play($i && note.userId === $i.id ? "noteMy" : "note");
}
if (props.sound) {
sound.play($i && n.user.id === $i.id ? "noteMy" : "note");
}
});
};
const onUserAdded = () => {

View File

@ -7,7 +7,7 @@
]"
:to="userPage(user)"
>
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="user"
:disable-link="true"

View File

@ -6,7 +6,7 @@
user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''
"
></div>
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="user"
:disable-preview="true"
@ -57,6 +57,7 @@ import MkFollowButton from "@/components/MkFollowButton.vue";
import MkNumber from "@/components/MkNumber.vue";
import { userPage } from "@/filters/user";
import { i18n } from "@/i18n";
import { $i } from "@/account";
defineProps<{
user: misskey.entities.UserDetailed;

View File

@ -42,7 +42,7 @@
@click="selected = user"
@dblclick="ok()"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="user"
class="avatar"
:show-indicator="true"
@ -70,7 +70,7 @@
@click="selected = user"
@dblclick="ok()"
>
<MkAvatar
<MagAvatar
:user="user"
class="avatar"
:show-indicator="true"
@ -88,7 +88,7 @@
</template>
<script lang="ts" setup>
import { nextTick, onMounted } from "vue";
import { onMounted } from "vue";
import * as misskey from "calckey-js";
import MkInput from "@/components/form/input.vue";
import FormSplit from "@/components/form/split.vue";

View File

@ -7,7 +7,7 @@
>
<div class="beaffaef">
<div v-for="u in users" :key="u.id" class="user">
<MkAvatar class="avatar" :user="u" disableLink />
<MagAvatarResolvingProxy class="avatar" :user="u" disableLink />
<MkUserName class="name" :user="u" :nowrap="true" />
</div>
<div v-if="users.length < count" class="omitted">
@ -18,7 +18,6 @@
</template>
<script lang="ts" setup>
import {} from "vue";
import MkTooltip from "./MkTooltip.vue";
const props = defineProps<{

View File

@ -4,13 +4,7 @@
v-user-preview="disablePreview ? undefined : user.id"
class="eiwwqkts _noSelect"
:class="{
cat:
magTransMap(
props.user,
'avatar_decoration',
'isCat',
(a) => a === 'CatEars'
) || false,
cat: props.user.avatar_decoration === 'CatEars' || false,
square: $store.state.squareAvatars,
}"
:style="{ color }"
@ -24,13 +18,7 @@
v-user-preview="disablePreview ? undefined : user.id"
class="eiwwqkts _noSelect"
:class="{
cat:
magTransMap(
props.user,
'avatar_decoration',
'isCat',
(d) => d === 'CatEars'
) || false,
cat: props.user.avatar_decoration === 'CatEars' || false,
square: $store.state.squareAvatars,
}"
:style="{ color }"
@ -45,17 +33,15 @@
<script lang="ts" setup>
import { watch } from "vue";
import * as misskey from "calckey-js";
import { getStaticImageUrl } from "@/scripts/get-static-image-url";
import { extractAvgColorFromBlurhash } from "@/scripts/extract-avg-color-from-blurhash";
import { acct, userPage } from "@/filters/user";
import { defaultStore } from "@/store";
import { packed } from "magnetar-common";
import { magTransMap, magTransProperty } from "@/scripts-mag/mag-util";
const props = withDefaults(
defineProps<{
user: packed.PackUserBase | misskey.entities.User;
user: packed.PackUserBase;
target?: string | null;
disableLink?: boolean;
disablePreview?: boolean;
@ -73,10 +59,8 @@ const emit = defineEmits<{
const url = $computed(() =>
defaultStore.state.disableShowingAnimatedImages
? getStaticImageUrl(
magTransProperty(props.user, "avatar_url", "avatarUrl")
)
: magTransProperty(props.user, "avatar_url", "avatarUrl")
? getStaticImageUrl(props.user.avatar_url)
: props.user.avatar_url
);
function onClick(ev: MouseEvent) {
@ -86,11 +70,9 @@ function onClick(ev: MouseEvent) {
let color = $ref<string>();
watch(
() => magTransProperty(props.user, "avatar_blurhash", "avatarBlurhash"),
() => props.user.avatar_blurhash,
() => {
color = extractAvgColorFromBlurhash(
magTransProperty(props.user, "avatar_blurhash", "avatarBlurhash")
);
color = extractAvgColorFromBlurhash(props.user.avatar_blurhash);
},
{
immediate: true,

View File

@ -0,0 +1,43 @@
<template>
<MagAvatar v-if="userResolved" :user="userResolved" />
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import { userIsMag } from "@/scripts-mag/mag-util";
import { endpoints, packed } from "magnetar-common";
import type * as Misskey from "calckey-js";
import * as os from "@/os";
const props = withDefaults(
defineProps<{
user: packed.PackUserBase | Misskey.entities.User;
target?: string | null;
disableLink?: boolean;
disablePreview?: boolean;
}>(),
{
target: null,
disableLink: false,
disablePreview: false,
}
);
const userResolved = ref<packed.PackUserBase | null>(null);
watch(
() => props.user,
async (val) => {
if (userIsMag(val)) {
userResolved.value = val;
}
userResolved.value = await os.magApi(
endpoints.GetUserById,
{},
{ user_id: val.id }
);
},
{ immediate: true }
);
</script>

View File

@ -18,7 +18,7 @@
>
<i class="ph-caret-left ph-bold ph-lg"></i>
</button>
<MkAvatar
<MagAvatarResolvingProxy
v-if="narrow && props.displayMyAvatar && $i"
class="avatar button"
:user="$i"
@ -32,7 +32,7 @@
class="titleContainer"
@click="showTabsPopup"
>
<MkAvatar
<MagAvatar
v-if="metadata.avatar"
class="avatar"
:user="metadata.avatar"

View File

@ -1,8 +1,5 @@
import * as Misskey from "calckey-js";
import { packed } from "magnetar-common";
export const notePage = (note: {
id: packed.PackNoteBase["id"] | Misskey.entities.Note["id"];
}) => {
export const notePage = (note: { id: packed.PackNoteBase["id"] }) => {
return `/notes/${note.id}`;
};

View File

@ -46,7 +46,8 @@ import { getAccountFromId } from "@/scripts/get-account-from-id";
import Mfm from "./components/global/MkMisskeyFlavoredMarkdown.vue";
import MkA from "./components/global/MkA.vue";
import MkAcct from "./components/global/MkAcct.vue";
import MkAvatar from "./components/global/MkAvatar.vue";
import MagAvatar from "./components/global/MagAvatar.vue";
import MagAvatarResolvingProxy from "./components/global/MagAvatarResolvingProxy.vue";
import MagEmoji from "./components/global/MagEmoji.vue";
import MkUserName from "./components/global/MkUserName.vue";
import MkEllipsis from "./components/global/MkEllipsis.vue";
@ -67,7 +68,7 @@ function globalComponents(app: App) {
app.component("Mfm", Mfm);
app.component("MkA", MkA);
app.component("MkAcct", MkAcct);
app.component("MkAvatar", MkAvatar);
app.component("MagAvatar", MagAvatar);
app.component("MagEmoji", MagEmoji);
app.component("MkUserName", MkUserName);
app.component("MkEllipsis", MkEllipsis);
@ -79,6 +80,7 @@ function globalComponents(app: App) {
app.component("MkPageHeader", MkPageHeader);
app.component("MkSpacer", MkSpacer);
app.component("MkStickyContainer", MkStickyContainer);
app.component("MagAvatarResolvingProxy", MagAvatarResolvingProxy);
}
declare module "@vue/runtime-core" {
@ -88,7 +90,7 @@ declare module "@vue/runtime-core" {
Mfm: typeof Mfm;
MkA: typeof MkA;
MkAcct: typeof MkAcct;
MkAvatar: typeof MkAvatar;
MagAvatar: typeof MagAvatar;
MagEmoji: typeof MagEmoji;
MkUserName: typeof MkUserName;
MkEllipsis: typeof MkEllipsis;
@ -100,6 +102,7 @@ declare module "@vue/runtime-core" {
MkPageHeader: typeof MkPageHeader;
MkSpacer: typeof MkSpacer;
MkStickyContainer: typeof MkStickyContainer;
MagAvatarResolvingProxy: typeof MagAvatarResolvingProxy;
}
}

View File

@ -66,6 +66,7 @@ import {
definePageMetadata,
provideMetadataReceiver,
} from "@/scripts/page-metadata";
import { endpoints } from "magnetar-common";
const isEmpty = (x: string | null) => x == null || x === "";
const el = ref<HTMLElement | null>(null);
@ -332,12 +333,18 @@ async function lookupNote() {
});
if (canceled) return;
os.api(
"notes/show",
q.startsWith("http://") || q.startsWith("https://")
? { url: q.trim() }
: { noteId: q.trim() }
)
if (q?.startsWith("http://") || q?.startsWith("https://")) {
const obj = await os.api("ap/show", {
uri: q,
});
if (obj.type === "Note") {
os.pageWindow(`/notes/${obj.object.id}`);
}
return;
}
os.magApi(endpoints.GetNoteById, {}, { id: q.trim() })
.then((note) => {
os.pageWindow(`/notes/${note.id}`);
})

View File

@ -12,7 +12,7 @@
class="user"
:to="`/user-info/${user.id}`"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="user"
class="avatar"
indicator
@ -25,10 +25,8 @@
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import { onMounted } from "vue";
import * as os from "@/os";
import number from "@/filters/number";
import { i18n } from "@/i18n";
let moderators: any = $ref(null);
let fetching = $ref(true);

View File

@ -1,6 +1,6 @@
<template>
<MkA :class="[$style.root]" :to="`/user-info/${user.id}`">
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="user"
:disable-link="true"

View File

@ -12,7 +12,7 @@
/>
</div>
<div class="user">
<MkAvatar
<MagAvatarResolvingProxy
:user="clip.user"
class="avatar"
:show-indicator="true"
@ -28,7 +28,7 @@
</template>
<script lang="ts" setup>
import { computed, watch, provide } from "vue";
import { computed, provide, watch } from "vue";
import type * as misskey from "calckey-js";
import XNotes from "@/components/MkNotes.vue";
import { $i } from "@/account";

View File

@ -37,11 +37,5 @@ const paginationForRemote = {
},
};
// const paginationForRemote = {
// endpoint: 'notes/polls/recommendation' as const,
// limit: 10,
// offsetMode: true,
// };
let tab = $ref("local");
</script>

View File

@ -23,7 +23,7 @@
:key="req.id"
class="user _panel"
>
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="req.follower"
:show-indicator="true"

View File

@ -92,7 +92,10 @@
</div>
</div>
<div class="user">
<MkAvatar :user="post.user" class="avatar" />
<MagAvatarResolvingProxy
:user="post.user"
class="avatar"
/>
<div class="name">
<MkUserName
:user="post.user"
@ -157,6 +160,7 @@ import { useRouter } from "@/router";
import { i18n } from "@/i18n";
import { definePageMetadata } from "@/scripts/page-metadata";
import { shareAvailable } from "@/scripts/share-available";
import { $i } from "@/account";
const router = useRouter();

View File

@ -10,7 +10,7 @@
:key="user.id"
class="user _panel"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="user"
class="avatar"
:show-indicator="true"

View File

@ -37,7 +37,7 @@
:key="user.id"
class="user _panel"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="user"
class="avatar"
:show-indicator="true"

View File

@ -141,7 +141,10 @@
</button>
</div>
<div class="user">
<MkAvatar :user="page.user" class="avatar" />
<MagAvatarResolvingProxy
:user="page.user"
class="avatar"
/>
<div class="name">
<MkUserName
:user="page.user"
@ -213,6 +216,7 @@ import { i18n } from "@/i18n";
import copyToClipboard from "@/scripts/copy-to-clipboard";
import { definePageMetadata } from "@/scripts/page-metadata";
import { shareAvailable } from "@/scripts/share-available";
import { $i } from "@/account";
const props = defineProps<{
pageName: string;

View File

@ -13,7 +13,11 @@
@click="menu(account, $event)"
>
<div class="avatar">
<MkAvatar :user="account" class="avatar" disableLink />
<MagAvatarResolvingProxy
:user="account"
class="avatar"
disableLink
/>
</div>
<div class="body">
<div class="name">
@ -34,11 +38,11 @@ import FormSuspense from "@/components/form/suspense.vue";
import FormButton from "@/components/MkButton.vue";
import * as os from "@/os";
import {
getAccounts,
addAccount as addAccounts,
removeAccount as _removeAccount,
login,
$i,
addAccount as addAccounts,
getAccounts,
login,
removeAccount as _removeAccount,
} from "@/account";
import { i18n } from "@/i18n";
import { definePageMetadata } from "@/scripts/page-metadata";

View File

@ -11,7 +11,7 @@
}"
>
<div class="avatar">
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="$i"
:disable-link="true"

View File

@ -32,16 +32,16 @@
<script lang="ts" setup>
// SPECIFICATION: https://misskey-hub.net/docs/features/share-form.html
import {} from "vue";
import * as Misskey from "calckey-js";
import { noteVisibilities } from "calckey-js";
import * as Acct from "calckey-js/built/acct";
import * as Misskey from "calckey-js";
import MkButton from "@/components/MkButton.vue";
import XPostForm from "@/components/MkPostForm.vue";
import * as os from "@/os";
import { mainRouter } from "@/router";
import { definePageMetadata } from "@/scripts/page-metadata";
import { i18n } from "@/i18n";
import { endpoints, packed } from "magnetar-common";
const urlParams = new URLSearchParams(window.location.search);
const localOnlyQuery = urlParams.get("localOnly");
@ -51,9 +51,9 @@ let state = $ref("fetching" as "fetching" | "writing" | "posted");
let title = $ref(urlParams.get("title"));
const text = urlParams.get("text");
const url = urlParams.get("url");
let initialText = $ref(null as string | null);
let reply = $ref(null as Misskey.entities.Note | null);
let renote = $ref(null as Misskey.entities.Note | null);
let initialText = $ref<string | null>(null);
let reply = $ref<packed.PackNoteMaybeFull | null>(null);
let renote = $ref<packed.PackNoteMaybeFull | null>(null);
let visibility = $ref(
noteVisibilities.includes(visibilityQuery) ? visibilityQuery : null
);
@ -114,15 +114,21 @@ async function init() {
const replyId = urlParams.get("replyId");
const replyUri = urlParams.get("replyUri");
if (replyId) {
reply = await os.api("notes/show", {
noteId: replyId,
});
reply = await os.magApi(
endpoints.GetNoteById,
{ attachments: true, context: true },
{ id: replyId }
);
} else if (replyUri) {
const obj = await os.api("ap/show", {
uri: replyUri,
});
if (obj.type === "Note") {
reply = obj.object;
reply = await os.magApi(
endpoints.GetNoteById,
{ attachments: true, context: true },
{ id: obj.object.id }
);
}
}
//#endregion
@ -131,15 +137,21 @@ async function init() {
const renoteId = urlParams.get("renoteId");
const renoteUri = urlParams.get("renoteUri");
if (renoteId) {
renote = await os.api("notes/show", {
noteId: renoteId,
});
renote = await os.magApi(
endpoints.GetNoteById,
{ attachments: true, context: true },
{ id: renoteId }
);
} else if (renoteUri) {
const obj = await os.api("ap/show", {
uri: renoteUri,
});
if (obj.type === "Note") {
renote = obj.object;
renote = await os.magApi(
endpoints.GetNoteById,
{ attachments: true, context: true },
{ id: obj.object.id }
);
}
}
//#endregion

View File

@ -10,7 +10,7 @@
<FormSuspense :p="init">
<div v-if="tab === 'overview'" class="_formRoot">
<div class="_formBlock aeakzknw">
<MkAvatar
<MagAvatarResolvingProxy
class="avatar"
:user="user"
:show-indicator="true"
@ -349,7 +349,6 @@ import FormLink from "@/components/form/link.vue";
import FormSection from "@/components/form/section.vue";
import FormButton from "@/components/MkButton.vue";
import FormInput from "@/components/form/input.vue";
import FormSplit from "@/components/form/split.vue";
import FormFolder from "@/components/form/folder.vue";
import MkKeyValue from "@/components/MkKeyValue.vue";
import MkSelect from "@/components/form/select.vue";
@ -357,13 +356,11 @@ import FormSuspense from "@/components/form/suspense.vue";
import MkFileListForAdmin from "@/components/MkFileListForAdmin.vue";
import MkInfo from "@/components/MkInfo.vue";
import * as os from "@/os";
import number from "@/filters/number";
import bytes from "@/filters/bytes";
import { url } from "@/config";
import { userPage, acct } from "@/filters/user";
import { acct, userPage } from "@/filters/user";
import { definePageMetadata } from "@/scripts/page-metadata";
import { i18n } from "@/i18n";
import { iAmAdmin, iAmModerator } from "@/account";
import { $i, iAmAdmin, iAmModerator } from "@/account";
import { instance } from "@/instance";
const props = defineProps<{

View File

@ -119,7 +119,7 @@
</div>
</div>
</div>
<MkAvatar
<MagAvatar
class="avatar"
:user="user"
:disable-preview="true"
@ -392,7 +392,6 @@ import { i18n } from "@/i18n";
import { $i } from "@/account";
import MkFollowApproveButton from "@/components/MkFollowApproveButton.vue";
import MkUserName from "@/components/global/MkUserName.vue";
import MkAvatar from "@/components/global/MkAvatar.vue";
import Mfm from "@/components/mfm.vue";
import MkTime from "@/components/global/MkTime.vue";
import MkA from "@/components/global/MkA.vue";

View File

@ -13,14 +13,13 @@
<script lang="ts" setup>
import { computed, ref } from "vue";
import * as misskey from "calckey-js";
import XNotes from "@/components/MkNotes.vue";
import MkTab from "@/components/MkTab.vue";
import { i18n } from "@/i18n";
import { packed } from "magnetar-common";
const props = defineProps<{
user: packed.PackUserBase | misskey.entities.UserDetailed;
user: packed.PackUserBase;
}>();
const include = ref<string | null>(null);

View File

@ -8,7 +8,7 @@
class="item _panel _gap afdcfbfb"
>
<div class="header">
<MkAvatar class="avatar" :user="user" />
<MagAvatar class="avatar" :user="user" />
<MkReactionIcon
class="reaction"
:reaction="item.type"
@ -25,13 +25,13 @@
<script lang="ts" setup>
import { computed } from "vue";
import * as misskey from "calckey-js";
import MkPagination from "@/components/MkPagination.vue";
import XNoteResolvingProxy from "@/components/MagNoteResolvingProxy.vue";
import MkReactionIcon from "@/components/MkReactionIcon.vue";
import { packed } from "magnetar-common";
const props = defineProps<{
user: misskey.entities.User;
user: packed.PackUserBase;
}>();
const pagination = {

View File

@ -131,6 +131,12 @@ export function magReactionSelf(
return null;
}
export function userIsMag(
user: packed.PackUserBase | Misskey.entities.User
): user is packed.PackUserBase {
return "created_at" in user;
}
export function noteIsMag(
note: packed.PackNoteMaybeFull | Misskey.entities.Note
): note is packed.PackNoteMaybeFull {

View File

@ -1,6 +1,4 @@
import { packed } from "magnetar-common";
import * as Misskey from "calckey-js";
import { magTransMap, magTransProperty } from "@/scripts-mag/mag-util";
export type Muted = {
muted: boolean;
@ -11,13 +9,12 @@ export type Muted = {
export type NotMuted = { muted: false; matched: string[] };
function checkWordMute(
note: packed.PackNoteMaybeFull | Misskey.entities.Note,
note: packed.PackNoteMaybeFull,
mutedWords: Array<string | string[]>
): Muted {
let text = `${note.cw ?? ""} ${note.text ?? ""}`;
const attachments = magTransProperty(note, "attachments", "files");
if (attachments)
text += ` ${attachments.map((f) => f.comment ?? "").join(" ")}`;
if (note.attachments)
text += ` ${note.attachments?.map((f) => f.comment ?? "")?.join(" ")}`;
text = text.trim();
let result: Muted | NotMuted = { muted: false, matched: [] };
@ -64,12 +61,12 @@ function checkWordMute(
}
export function getWordSoftMute(
note: packed.PackNoteMaybeFull | Misskey.entities.Note,
note: packed.PackNoteMaybeFull,
me: Record<string, any> | null | undefined,
mutedWords: Array<string | string[]>
): Muted {
// 自分自身
if (me && magTransMap(note, "user", "userId", (u) => u.id) === me.id) {
if (me && note.user.id === me.id) {
return { muted: false, matched: [] };
}
@ -80,18 +77,16 @@ export function getWordSoftMute(
return noteMuted;
}
const renote = magTransProperty(note, "renoted_note", "renote");
if (renote) {
let renoteMuted = checkWordMute(renote, mutedWords);
if (note.renoted_note) {
let renoteMuted = checkWordMute(note.renoted_note, mutedWords);
if (renoteMuted.muted) {
renoteMuted.what = note.text == null ? "renote" : "quote";
return renoteMuted;
}
}
const reply = magTransProperty(note, "parent_note", "reply");
if (reply) {
let replyMuted = checkWordMute(reply, mutedWords);
if (note.parent_note) {
let replyMuted = checkWordMute(note.parent_note, mutedWords);
if (replyMuted.muted) {
replyMuted.what = "reply";
return replyMuted;

View File

@ -2,13 +2,13 @@ import * as Acct from "calckey-js/built/acct";
import { host as localHost } from "@/config";
export async function genSearchQuery(v: any, q: string) {
let host: string;
let host: string | null;
let userId: string;
if (q.split(" ").some((x) => x.startsWith("@"))) {
for (const at of q
.split(" ")
.filter((x) => x.startsWith("@"))
.map((x) => x.substr(1))) {
.map((x) => x.substring(1))) {
if (at.includes(".")) {
if (at === localHost || at === ".") {
host = null;

View File

@ -1,14 +1,10 @@
import * as misskey from "calckey-js";
import { packed } from "magnetar-common";
import { magTransProperty } from "@/scripts-mag/mag-util";
/**
* 稿
* @param {*} note (packされた)稿
*/
export const getNoteSummary = (
note: packed.PackNoteMaybeFull | misskey.entities.Note
): string => {
export const getNoteSummary = (note: packed.PackNoteMaybeFull): string => {
/*
if (note.deletedAt) {
return `(${i18n.ts.deletedNote})`;
@ -25,9 +21,8 @@ export const getNoteSummary = (
}
// ファイルが添付されているとき
const files = magTransProperty(note, "attachments", "files");
if ((files || []).length !== 0) {
const len = files?.length;
if ((note.attachments || []).length !== 0) {
const len = note.attachments?.length;
summary += ` 📎${len !== 1 ? ` (${len})` : ""}`;
}

View File

@ -8,7 +8,7 @@ export async function lookupUser() {
});
if (canceled) return;
const show = (user) => {
const show = (user: { id: any }) => {
os.pageWindow(`/user-info/${user.id}`);
};
@ -25,12 +25,10 @@ export async function lookupUser() {
_notFound = true;
}
};
usernamePromise.then(show).catch((err) => {
if (err.code === "NO_SUCH_USER") {
Promise.any([usernamePromise, idPromise])
.then(show)
.catch(() => {
notFound();
}
});
idPromise.then(show).catch((err) => {
notFound();
});
});
}

View File

@ -1,4 +1,3 @@
import * as misskey from "calckey-js";
import {
ComputedRef,
inject,
@ -18,8 +17,8 @@ export type PageMetadata = {
title: string;
subtitle?: string;
icon?: string | null;
avatar?: packed.PackUserBase | misskey.entities.User | null;
userName?: packed.PackUserBase | misskey.entities.User | null;
avatar?: packed.PackUserBase | null;
userName?: packed.PackUserBase | null;
bg?: string;
};

View File

@ -15,7 +15,7 @@
class="item _button account"
@click="openAccountMenu"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="$i"
class="icon"
disableLink
@ -118,17 +118,10 @@
</template>
<script lang="ts" setup>
import {
computed,
defineAsyncComponent,
defineComponent,
ref,
toRef,
watch,
} from "vue";
import { computed, defineAsyncComponent, toRef } from "vue";
import * as os from "@/os";
import { navbarItemDef } from "@/navbar";
import { openAccountMenu as openAccountMenu_ } from "@/account";
import { $i, openAccountMenu as openAccountMenu_ } from "@/account";
import { openHelpMenu_ } from "@/scripts/helpMenu";
import { defaultStore } from "@/store";
import { i18n } from "@/i18n";

View File

@ -15,7 +15,7 @@
class="item _button account"
@click="openAccountMenu"
>
<MkAvatar
<MagAvatarResolvingProxy
:user="$i"
class="icon"
disableLink
@ -133,12 +133,6 @@
>
<i class="help icon ph-info ph-bold ph-xl ph-fw"></i>
</button>
<!-- <button v-click-anime v-tooltip.noDelay.right="$instance.name ?? i18n.ts.instance" class="item _button instance" @click="openInstanceMenu">
<img :src="$instance.iconUrl || $instance.faviconUrl || '/favicon.ico'" alt="" class="icon"/>
</button> -->
<!-- <button v-click-anime v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="item _button account" @click="openAccountMenu">
<MkAvatar :user="$i" class="account"/><MkAcct class="text" :user="$i"/>
</button> -->
</div>
</div>
</header>

View File

@ -10,7 +10,7 @@
<span v-for="note in notes" :key="note.id" class="item">
<img
class="avatar"
:src="note.user.avatarUrl"
:src="note.user.avatar_url"
decoding="async"
/>
<MkA class="text" :to="notePage(note)">
@ -34,13 +34,14 @@
</template>
<script lang="ts" setup>
import { computed, defineAsyncComponent, ref, toRef, watch } from "vue";
import * as misskey from "calckey-js";
import { ref, watch } from "vue";
import MarqueeText from "@/components/MkMarquee.vue";
import * as os from "@/os";
import { useInterval } from "@/scripts/use-interval";
import { getNoteSummary } from "@/scripts/get-note-summary";
import { notePage } from "@/filters/note";
import { resolveNote } from "@/scripts-mag/mag-util";
import { packed } from "magnetar-common";
const props = defineProps<{
userListId?: string;
@ -51,7 +52,7 @@ const props = defineProps<{
refreshIntervalSec?: number;
}>();
const notes = ref<misskey.entities.Note[]>([]);
const notes = ref<packed.PackNoteMaybeFull[]>([]);
const fetching = ref(true);
let key = $ref(0);
@ -59,8 +60,8 @@ const tick = () => {
if (props.userListId == null) return;
os.api("notes/user-list-timeline", {
listId: props.userListId,
}).then((res) => {
notes.value = res;
}).then(async (res) => {
notes.value = await Promise.all(res.map(resolveNote));
fetching.value = false;
key++;
});

View File

@ -63,8 +63,8 @@
>
<small
>Powered by
<a href="https://calckey.org/" target="_blank"
>Calckey</a
<a href="https://git.astolfo.cool/natty/magnetar" target="_blank"
>Magnetar</a
></small
>
</div>

View File

@ -18,8 +18,8 @@
>
<small
>Powered by
<a href="https://calckey.org/" target="_blank"
>Calckey</a
<a href="https://git.astolfo.cool/natty/magnetar" target="_blank"
>Magnetar</a
></small
>
</div>

View File

@ -29,7 +29,7 @@
<div v-if="info" class="page active link">
<div class="title">
<i v-if="info.icon" class="icon" :class="info.icon"></i>
<MkAvatar
<MagAvatarResolvingProxy
v-else-if="info.avatar"
class="avatar"
:user="info.avatar"
@ -74,7 +74,7 @@
</button>
<div v-if="info" class="title">
<i v-if="info.icon" class="icon" :class="info.icon"></i>
<MkAvatar
<MagAvatarResolvingProxy
v-else-if="info.avatar"
class="avatar"
:user="info.avatar"

View File

@ -69,8 +69,8 @@
>
<small
>Powered by
<a href="https://calckey.org/" target="_blank"
>Calckey</a
<a href="https://git.astolfo.cool/natty/magnetar" target="_blank"
>Magnetar</a
></small
>
</div>