fix types of components
This commit is contained in:
parent
ea6ef881c2
commit
e4927c9b9b
38 changed files with 319 additions and 159 deletions
|
@ -20,15 +20,10 @@ import { ref } from "vue";
|
|||
import { instanceName, version } from "@/config";
|
||||
import { instance as Instance } from "@/instance";
|
||||
import { getProxiedImageUrlNullable } from "@/scripts/media-proxy";
|
||||
import type { entities } from "firefish-js";
|
||||
|
||||
const props = defineProps<{
|
||||
instance?: {
|
||||
faviconUrl?: string;
|
||||
name: string;
|
||||
themeColor?: string;
|
||||
softwareName?: string;
|
||||
softwareVersion?: string;
|
||||
};
|
||||
instance?: entities.InstanceLite;
|
||||
}>();
|
||||
|
||||
const ticker = ref<HTMLElement | null>(null);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
v-vibrate="5"
|
||||
:aria-label="accessibleLabel"
|
||||
class="tkcbzcuz note-container"
|
||||
:tabindex="!isDeleted ? '-1' : null"
|
||||
:tabindex="!isDeleted ? '-1' : undefined"
|
||||
:class="{ renote: isRenote }"
|
||||
>
|
||||
<MkNoteSub
|
||||
|
@ -112,9 +112,9 @@
|
|||
:note="appearNote"
|
||||
:detailed="true"
|
||||
:detailed-view="detailedView"
|
||||
:parent-id="appearNote.parentId"
|
||||
:parent-id="appearNote.id"
|
||||
@push="(e) => router.push(notePage(e))"
|
||||
@focusfooter="footerEl.focus()"
|
||||
@focusfooter="footerEl!.focus()"
|
||||
@expanded="(e) => setPostExpanded(e)"
|
||||
></MkSubNoteContent>
|
||||
<div v-if="translating || translation" class="translation">
|
||||
|
@ -312,11 +312,17 @@ import { notePage } from "@/filters/note";
|
|||
import { deepClone } from "@/scripts/clone";
|
||||
import { getNoteSummary } from "@/scripts/get-note-summary";
|
||||
import icon from "@/scripts/icon";
|
||||
import type { NoteTranslation } from "@/types/note";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
type NoteType = entities.Note & {
|
||||
_featuredId_?: string;
|
||||
_prId_?: string;
|
||||
};
|
||||
|
||||
const props = defineProps<{
|
||||
note: entities.Note;
|
||||
note: NoteType;
|
||||
pinned?: boolean;
|
||||
detailedView?: boolean;
|
||||
collapsedReply?: boolean;
|
||||
|
@ -354,18 +360,18 @@ const isRenote =
|
|||
note.value.fileIds.length === 0 &&
|
||||
note.value.poll == null;
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const el = ref<HTMLElement | null>(null);
|
||||
const footerEl = ref<HTMLElement>();
|
||||
const menuButton = ref<HTMLElement>();
|
||||
const starButton = ref<InstanceType<typeof XStarButton>>();
|
||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||
const renoteButton = ref<InstanceType<typeof XRenoteButton> | null>(null);
|
||||
const renoteTime = ref<HTMLElement>();
|
||||
const reactButton = ref<HTMLElement>();
|
||||
const reactButton = ref<HTMLElement | null>(null);
|
||||
const appearNote = computed(() =>
|
||||
isRenote ? (note.value.renote as entities.Note) : note.value,
|
||||
isRenote ? (note.value.renote as NoteType) : note.value,
|
||||
);
|
||||
const isMyRenote = isSignedIn && me.id === note.value.userId;
|
||||
const showContent = ref(false);
|
||||
const isMyRenote = isSignedIn && me!.id === note.value.userId;
|
||||
// const showContent = ref(false);
|
||||
const isDeleted = ref(false);
|
||||
const muted = ref(
|
||||
getWordSoftMute(
|
||||
|
@ -375,7 +381,7 @@ const muted = ref(
|
|||
defaultStore.state.mutedLangs,
|
||||
),
|
||||
);
|
||||
const translation = ref(null);
|
||||
const translation = ref<NoteTranslation | null>(null);
|
||||
const translating = ref(false);
|
||||
const enableEmojiReactions = defaultStore.state.enableEmojiReactions;
|
||||
const expandOnNoteClick = defaultStore.state.expandOnNoteClick;
|
||||
|
@ -391,7 +397,7 @@ const isForeignLanguage: boolean =
|
|||
return postLang !== "" && postLang !== targetLang;
|
||||
})();
|
||||
|
||||
async function translate_(noteId, targetLang: string) {
|
||||
async function translate_(noteId: string, targetLang: string) {
|
||||
return await os.api("notes/translate", {
|
||||
noteId,
|
||||
targetLang,
|
||||
|
@ -421,12 +427,13 @@ async function translate() {
|
|||
const keymap = {
|
||||
r: () => reply(true),
|
||||
"e|a|plus": () => react(true),
|
||||
q: () => renoteButton.value.renote(true),
|
||||
q: () => renoteButton.value!.renote(true),
|
||||
"up|k": focusBefore,
|
||||
"down|j": focusAfter,
|
||||
esc: blur,
|
||||
"m|o": () => menu(true),
|
||||
s: () => showContent.value !== showContent.value,
|
||||
// FIXME: What's this?
|
||||
// s: () => showContent.value !== showContent.value,
|
||||
};
|
||||
|
||||
if (appearNote.value.historyId == null) {
|
||||
|
@ -437,12 +444,12 @@ if (appearNote.value.historyId == null) {
|
|||
});
|
||||
}
|
||||
|
||||
function reply(viaKeyboard = false): void {
|
||||
function reply(_viaKeyboard = false): void {
|
||||
pleaseLogin();
|
||||
os.post(
|
||||
{
|
||||
reply: appearNote.value,
|
||||
animation: !viaKeyboard,
|
||||
// animation: !viaKeyboard,
|
||||
},
|
||||
() => {
|
||||
focus();
|
||||
|
@ -450,11 +457,11 @@ function reply(viaKeyboard = false): void {
|
|||
);
|
||||
}
|
||||
|
||||
function react(viaKeyboard = false): void {
|
||||
function react(_viaKeyboard = false): void {
|
||||
pleaseLogin();
|
||||
blur();
|
||||
reactionPicker.show(
|
||||
reactButton.value,
|
||||
reactButton.value!,
|
||||
(reaction) => {
|
||||
os.api("notes/reactions/create", {
|
||||
noteId: appearNote.value.id,
|
||||
|
@ -467,7 +474,7 @@ function react(viaKeyboard = false): void {
|
|||
);
|
||||
}
|
||||
|
||||
function undoReact(note): void {
|
||||
function undoReact(note: NoteType): void {
|
||||
const oldReaction = note.myReaction;
|
||||
if (!oldReaction) return;
|
||||
os.api("notes/reactions/delete", {
|
||||
|
@ -481,16 +488,17 @@ const currentClipPage = inject<Ref<entities.Clip> | null>(
|
|||
);
|
||||
|
||||
function onContextmenu(ev: MouseEvent): void {
|
||||
const isLink = (el: HTMLElement) => {
|
||||
const isLink = (el: HTMLElement): boolean => {
|
||||
if (el.tagName === "A") return true;
|
||||
// The Audio element's context menu is the browser default, such as for selecting playback speed.
|
||||
if (el.tagName === "AUDIO") return true;
|
||||
if (el.parentElement) {
|
||||
return isLink(el.parentElement);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (isLink(ev.target)) return;
|
||||
if (window.getSelection().toString() !== "") return;
|
||||
if (isLink(ev.target as HTMLElement)) return;
|
||||
if (window.getSelection()?.toString() !== "") return;
|
||||
|
||||
if (defaultStore.state.useReactionPickerForContextMenu) {
|
||||
ev.preventDefault();
|
||||
|
@ -509,7 +517,7 @@ function onContextmenu(ev: MouseEvent): void {
|
|||
os.pageWindow(notePage(appearNote.value));
|
||||
},
|
||||
},
|
||||
notePage(appearNote.value) != location.pathname
|
||||
notePage(appearNote.value) !== location.pathname
|
||||
? {
|
||||
icon: `${icon("ph-arrows-out-simple")}`,
|
||||
text: i18n.ts.showInPage,
|
||||
|
@ -589,11 +597,11 @@ function showRenoteMenu(viaKeyboard = false): void {
|
|||
}
|
||||
|
||||
function focus() {
|
||||
el.value.focus();
|
||||
el.value!.focus();
|
||||
}
|
||||
|
||||
function blur() {
|
||||
el.value.blur();
|
||||
el.value!.blur();
|
||||
}
|
||||
|
||||
function focusBefore() {
|
||||
|
@ -605,12 +613,12 @@ function focusAfter() {
|
|||
}
|
||||
|
||||
function scrollIntoView() {
|
||||
el.value.scrollIntoView();
|
||||
el.value!.scrollIntoView();
|
||||
}
|
||||
|
||||
function noteClick(e) {
|
||||
if (
|
||||
document.getSelection().type === "Range" ||
|
||||
document.getSelection()?.type === "Range" ||
|
||||
props.detailedView ||
|
||||
!expandOnNoteClick
|
||||
) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
v-hotkey="keymap"
|
||||
v-size="{ max: [500, 350, 300] }"
|
||||
class="lxwezrsl _block"
|
||||
:tabindex="!isDeleted ? '-1' : null"
|
||||
:tabindex="!isDeleted ? '-1' : undefined"
|
||||
:class="{ renote: isRenote }"
|
||||
>
|
||||
<MkNoteSub
|
||||
|
@ -64,7 +64,7 @@
|
|||
)
|
||||
}}
|
||||
</option>
|
||||
<option v-if="directQuotes?.length > 0" value="quotes">
|
||||
<option v-if="directQuotes && directQuotes.length > 0" value="quotes">
|
||||
<!-- <i :class="icon('ph-quotes')"></i> -->
|
||||
{{
|
||||
wordWithCount(
|
||||
|
@ -102,7 +102,7 @@
|
|||
:detailed-view="true"
|
||||
:parent-id="note.id"
|
||||
/>
|
||||
<MkLoading v-else-if="tab === 'quotes' && directQuotes.length > 0" />
|
||||
<MkLoading v-else-if="tab === 'quotes' && directQuotes && directQuotes.length > 0" />
|
||||
|
||||
<!-- <MkPagination
|
||||
v-if="tab === 'renotes'"
|
||||
|
@ -225,12 +225,12 @@ if (noteViewInterruptors.length > 0) {
|
|||
});
|
||||
}
|
||||
|
||||
const el = ref<HTMLElement>();
|
||||
const el = ref<HTMLElement | null>(null);
|
||||
const noteEl = ref();
|
||||
const menuButton = ref<HTMLElement>();
|
||||
const renoteButton = ref<InstanceType<typeof XRenoteButton>>();
|
||||
const reactButton = ref<HTMLElement>();
|
||||
const showContent = ref(false);
|
||||
// const showContent = ref(false);
|
||||
const isDeleted = ref(false);
|
||||
const muted = ref(
|
||||
getWordSoftMute(
|
||||
|
@ -248,7 +248,8 @@ const directReplies = ref<null | entities.Note[]>([]);
|
|||
const directQuotes = ref<null | entities.Note[]>([]);
|
||||
const clips = ref();
|
||||
const renotes = ref();
|
||||
let isScrolling;
|
||||
const isRenote = ref(note.value.renoteId != null);
|
||||
let isScrolling: boolean;
|
||||
|
||||
const reactionsCount = Object.values(props.note.reactions).reduce(
|
||||
(x, y) => x + y,
|
||||
|
@ -258,10 +259,10 @@ const reactionsCount = Object.values(props.note.reactions).reduce(
|
|||
const keymap = {
|
||||
r: () => reply(true),
|
||||
"e|a|plus": () => react(true),
|
||||
q: () => renoteButton.value.renote(true),
|
||||
q: () => renoteButton.value!.renote(true),
|
||||
esc: blur,
|
||||
"m|o": () => menu(true),
|
||||
s: () => showContent.value !== showContent.value,
|
||||
// s: () => showContent.value !== showContent.value,
|
||||
};
|
||||
|
||||
useNoteCapture({
|
||||
|
@ -270,21 +271,21 @@ useNoteCapture({
|
|||
isDeletedRef: isDeleted,
|
||||
});
|
||||
|
||||
function reply(viaKeyboard = false): void {
|
||||
function reply(_viaKeyboard = false): void {
|
||||
pleaseLogin();
|
||||
os.post({
|
||||
reply: note.value,
|
||||
animation: !viaKeyboard,
|
||||
// animation: !viaKeyboard,
|
||||
}).then(() => {
|
||||
focus();
|
||||
});
|
||||
}
|
||||
|
||||
function react(viaKeyboard = false): void {
|
||||
function react(_viaKeyboard = false): void {
|
||||
pleaseLogin();
|
||||
blur();
|
||||
reactionPicker.show(
|
||||
reactButton.value,
|
||||
reactButton.value!,
|
||||
(reaction) => {
|
||||
os.api("notes/reactions/create", {
|
||||
noteId: note.value.id,
|
||||
|
@ -297,13 +298,13 @@ function react(viaKeyboard = false): void {
|
|||
);
|
||||
}
|
||||
|
||||
function undoReact(note): void {
|
||||
const oldReaction = note.myReaction;
|
||||
if (!oldReaction) return;
|
||||
os.api("notes/reactions/delete", {
|
||||
noteId: note.id,
|
||||
});
|
||||
}
|
||||
// function undoReact(note): void {
|
||||
// const oldReaction = note.myReaction;
|
||||
// if (!oldReaction) return;
|
||||
// os.api("notes/reactions/delete", {
|
||||
// noteId: note.id,
|
||||
// });
|
||||
// }
|
||||
|
||||
function onContextmenu(ev: MouseEvent): void {
|
||||
const isLink = (el: HTMLElement) => {
|
||||
|
@ -312,8 +313,8 @@ function onContextmenu(ev: MouseEvent): void {
|
|||
return isLink(el.parentElement);
|
||||
}
|
||||
};
|
||||
if (isLink(ev.target)) return;
|
||||
if (window.getSelection().toString() !== "") return;
|
||||
if (isLink(ev.target as HTMLElement)) return;
|
||||
if (window.getSelection()?.toString() !== "") return;
|
||||
|
||||
if (defaultStore.state.useReactionPickerForContextMenu) {
|
||||
ev.preventDefault();
|
||||
|
@ -362,12 +363,17 @@ os.api("notes/children", {
|
|||
limit: 30,
|
||||
depth: 12,
|
||||
}).then((res) => {
|
||||
res = res.reduce((acc, resNote) => {
|
||||
if (resNote.userId == note.value.userId) {
|
||||
return [...acc, resNote];
|
||||
}
|
||||
return [resNote, ...acc];
|
||||
}, []);
|
||||
// biome-ignore lint/style/noParameterAssign: assign it intentially
|
||||
res = res
|
||||
.filter((n) => n.userId !== note.value.userId)
|
||||
.reverse()
|
||||
.concat(res.filter((n) => n.userId === note.value.userId));
|
||||
// res = res.reduce((acc: entities.Note[], resNote) => {
|
||||
// if (resNote.userId === note.value.userId) {
|
||||
// return [...acc, resNote];
|
||||
// }
|
||||
// return [resNote, ...acc];
|
||||
// }, []);
|
||||
replies.value = res;
|
||||
directReplies.value = res
|
||||
.filter((resNote) => resNote.replyId === note.value.id)
|
||||
|
@ -438,7 +444,7 @@ async function onNoteUpdated(
|
|||
}
|
||||
|
||||
switch (type) {
|
||||
case "replied":
|
||||
case "replied": {
|
||||
const { id: createdId } = body;
|
||||
const replyNote = await os.api("notes/show", {
|
||||
noteId: createdId,
|
||||
|
@ -446,10 +452,10 @@ async function onNoteUpdated(
|
|||
|
||||
replies.value.splice(found, 0, replyNote);
|
||||
if (found === 0) {
|
||||
directReplies.value.push(replyNote);
|
||||
directReplies.value!.push(replyNote);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case "deleted":
|
||||
if (found === 0) {
|
||||
isDeleted.value = true;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div v-size="{ min: [350, 500] }" class="fefdfafb">
|
||||
<MkAvatar class="avatar" :user="me" disable-link />
|
||||
<MkAvatar class="avatar" :user="me!" disable-link />
|
||||
<div class="main">
|
||||
<div class="header">
|
||||
<MkUserName :user="me" />
|
||||
<MkUserName :user="me!" />
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="content">
|
||||
|
|
|
@ -40,7 +40,11 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import type { PagingOf } from "@/components/MkPagination.vue";
|
||||
import type {
|
||||
MkPaginationType,
|
||||
PagingKeyOf,
|
||||
PagingOf,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import XNote from "@/components/MkNote.vue";
|
||||
import XList from "@/components/MkDateSeparatedList.vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
|
@ -56,10 +60,14 @@ defineProps<{
|
|||
disableAutoLoad?: boolean;
|
||||
}>();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<
|
||||
PagingKeyOf<entities.Note>
|
||||
> | null>(null);
|
||||
|
||||
function scrollTop() {
|
||||
scroll(tlEl.value, { top: 0, behavior: "smooth" });
|
||||
if (tlEl.value) {
|
||||
scroll(tlEl.value, { top: 0, behavior: "smooth" });
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
:with-ok-button="true"
|
||||
:ok-button-disabled="false"
|
||||
@ok="ok()"
|
||||
@close="dialog.close()"
|
||||
@close="dialog!.close()"
|
||||
@closed="emit('closed')"
|
||||
>
|
||||
<template #header>{{ i18n.ts.notificationSetting }}</template>
|
||||
|
@ -68,7 +68,7 @@ const includingTypes = computed(() => props.includingTypes || []);
|
|||
|
||||
const dialog = ref<InstanceType<typeof XModalWindow>>();
|
||||
|
||||
const typesMap = ref<Record<(typeof notificationTypes)[number], boolean>>({});
|
||||
const typesMap = ref({} as Record<(typeof notificationTypes)[number], boolean>);
|
||||
const useGlobalSetting = ref(
|
||||
(includingTypes.value === null || includingTypes.value.length === 0) &&
|
||||
props.showGlobalToggle,
|
||||
|
@ -89,7 +89,7 @@ function ok() {
|
|||
});
|
||||
}
|
||||
|
||||
dialog.value.close();
|
||||
dialog.value!.close();
|
||||
}
|
||||
|
||||
function disableAll() {
|
||||
|
|
|
@ -19,9 +19,10 @@ import { onMounted, ref } from "vue";
|
|||
import XNotification from "@/components/MkNotification.vue";
|
||||
import * as os from "@/os";
|
||||
import { defaultStore } from "@/store";
|
||||
import type { entities } from "firefish-js";
|
||||
|
||||
defineProps<{
|
||||
notification: any; // TODO
|
||||
notification: entities.Notification;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||
import type { StreamTypes, entities, notificationTypes } from "firefish-js";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import XNotification from "@/components/MkNotification.vue";
|
||||
import XList from "@/components/MkDateSeparatedList.vue";
|
||||
import XNote from "@/components/MkNote.vue";
|
||||
|
@ -59,7 +61,7 @@ const props = defineProps<{
|
|||
|
||||
const stream = useStream();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<"i/notifications"> | null>(null);
|
||||
|
||||
const pagination = {
|
||||
endpoint: "i/notifications" as const,
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup generic="E extends PagingKey">
|
||||
import type { ComputedRef } from "vue";
|
||||
import type { ComponentPublicInstance, ComputedRef } from "vue";
|
||||
import { computed, isRef, onActivated, onDeactivated, ref, watch } from "vue";
|
||||
import type { Endpoints, TypeUtils } from "firefish-js";
|
||||
import * as os from "@/os";
|
||||
|
@ -81,8 +81,30 @@ import MkButton from "@/components/MkButton.vue";
|
|||
import { i18n } from "@/i18n";
|
||||
import { defaultStore } from "@/store";
|
||||
|
||||
/**
|
||||
* ref type of MkPagination<E>
|
||||
* Due to Vue's incomplete type support for generic components,
|
||||
* we have to manually maintain this type instead of
|
||||
* using `InstanceType<typeof MkPagination>`
|
||||
*/
|
||||
export type MkPaginationType<
|
||||
E extends PagingKey,
|
||||
Item = Endpoints[E]["res"][number],
|
||||
> = ComponentPublicInstance & {
|
||||
items: Item[];
|
||||
queue: Item[];
|
||||
backed: boolean;
|
||||
reload: () => Promise<void>;
|
||||
refresh: () => Promise<void>;
|
||||
prepend: (item: Item) => Promise<void>;
|
||||
append: (item: Item) => Promise<void>;
|
||||
removeItem: (finder: (item: Item) => boolean) => boolean;
|
||||
updateItem: (id: string, replacer: (old: Item) => Item) => boolean;
|
||||
};
|
||||
|
||||
export type PagingKeyOf<T> = TypeUtils.EndpointsOf<T[]>;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Used Intentionally
|
||||
export type PagingKey = TypeUtils.EndpointsOf<any[]>;
|
||||
export type PagingKey = PagingKeyOf<any>;
|
||||
|
||||
export interface Paging<E extends PagingKey = PagingKey> {
|
||||
endpoint: E;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<MkModal
|
||||
ref="modal"
|
||||
:prefer-type="'dialog'"
|
||||
@click="modal.close()"
|
||||
@click="modal!.close()"
|
||||
@closed="onModalClosed()"
|
||||
>
|
||||
<MkPostForm
|
||||
|
@ -12,8 +12,8 @@
|
|||
autofocus
|
||||
freeze-after-posted
|
||||
@posted="onPosted"
|
||||
@cancel="modal.close()"
|
||||
@esc="modal.close()"
|
||||
@cancel="modal!.close()"
|
||||
@esc="modal!.close()"
|
||||
/>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
|
|
@ -77,7 +77,7 @@ const hasRenotedBefore = ref(false);
|
|||
if (isSignedIn) {
|
||||
os.api("notes/renotes", {
|
||||
noteId: props.note.id,
|
||||
userId: me.id,
|
||||
userId: me!.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
hasRenotedBefore.value = res.length > 0;
|
||||
|
@ -251,6 +251,10 @@ const renote = (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
|
||||
os.popupMenu(buttonActions, buttonRef.value, { viaKeyboard });
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
renote,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
:text="note.cw"
|
||||
:author="note.user"
|
||||
:lang="note.lang"
|
||||
:i="me"
|
||||
:custom-emojis="note.emojis"
|
||||
/>
|
||||
</p>
|
||||
|
@ -63,8 +62,8 @@
|
|||
<div
|
||||
class="body"
|
||||
v-bind="{
|
||||
'aria-hidden': note.cw && !showContent ? 'true' : null,
|
||||
tabindex: !showContent ? '-1' : null,
|
||||
'aria-hidden': note.cw && !showContent ? 'true' : undefined,
|
||||
tabindex: !showContent ? '-1' : undefined,
|
||||
}"
|
||||
>
|
||||
<span v-if="note.deletedAt" style="opacity: 0.5"
|
||||
|
@ -103,7 +102,6 @@
|
|||
v-if="note.text"
|
||||
:text="note.text"
|
||||
:author="note.user"
|
||||
:i="me"
|
||||
:lang="note.lang"
|
||||
:custom-emojis="note.emojis"
|
||||
/>
|
||||
|
@ -256,7 +254,7 @@ async function toggleMfm() {
|
|||
}
|
||||
|
||||
function focusFooter(ev) {
|
||||
if (ev.key == "Tab" && !ev.getModifierState("Shift")) {
|
||||
if (ev.key === "Tab" && !ev.getModifierState("Shift")) {
|
||||
emit("focusfooter");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="{ items: users }">
|
||||
<template #default="{ items }: { items: entities.UserDetailed[] }">
|
||||
<div class="efvhhmdq">
|
||||
<MkUserInfo
|
||||
v-for="user in users"
|
||||
v-for="user in items"
|
||||
:key="user.id"
|
||||
class="user"
|
||||
:user="user"
|
||||
|
@ -27,16 +27,21 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import MkUserInfo from "@/components/MkUserInfo.vue";
|
||||
import type { Paging } from "@/components/MkPagination.vue";
|
||||
import type {
|
||||
MkPaginationType,
|
||||
PagingKeyOf,
|
||||
PagingOf,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import { i18n } from "@/i18n";
|
||||
import type { entities } from "firefish-js";
|
||||
|
||||
defineProps<{
|
||||
pagination: Paging;
|
||||
pagination: PagingOf<entities.UserDetailed>;
|
||||
noGap?: boolean;
|
||||
}>();
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<PagingKeyOf<entities.User>>>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -94,9 +94,9 @@ import { defaultStore } from "@/store";
|
|||
import { i18n } from "@/i18n";
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "ok", selected: entities.UserDetailed): void;
|
||||
(ev: "cancel"): void;
|
||||
(ev: "closed"): void;
|
||||
ok: [selected: entities.UserDetailed];
|
||||
cancel: [];
|
||||
closed: [];
|
||||
}>();
|
||||
|
||||
const username = ref("");
|
||||
|
@ -114,7 +114,7 @@ const search = () => {
|
|||
query: username.value,
|
||||
origin: "local",
|
||||
limit: 10,
|
||||
detail: false,
|
||||
detail: true,
|
||||
}).then((_users) => {
|
||||
users.value = _users;
|
||||
});
|
||||
|
@ -127,7 +127,7 @@ const ok = () => {
|
|||
|
||||
// 最近使ったユーザー更新
|
||||
let recents = defaultStore.state.recentlyUsedUsers;
|
||||
recents = recents.filter((x) => x !== selected.value.id);
|
||||
recents = recents.filter((x) => x !== selected.value!.id);
|
||||
recents.unshift(selected.value.id);
|
||||
defaultStore.set("recentlyUsedUsers", recents.splice(0, 16));
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@ withDefaults(
|
|||
text: string;
|
||||
plain?: boolean;
|
||||
nowrap?: boolean;
|
||||
author?: entities.User;
|
||||
author?: entities.User | null;
|
||||
customEmojis?: entities.EmojiLite[];
|
||||
isNote?: boolean;
|
||||
advancedMfm?: boolean;
|
||||
|
|
|
@ -30,7 +30,7 @@ export default defineComponent({
|
|||
default: false,
|
||||
},
|
||||
author: {
|
||||
type: Object as PropType<entities.User>,
|
||||
type: Object as PropType<entities.User | null>,
|
||||
default: null,
|
||||
},
|
||||
// TODO: This variable is not used in the code and may be removed
|
||||
|
|
|
@ -13,7 +13,7 @@ export const wsUrl = `${url
|
|||
export const lang = localStorage.getItem("lang");
|
||||
export const langs = _LANGS_;
|
||||
export const locale = JSON.parse(localStorage.getItem("locale") || "en-US");
|
||||
export const version = _VERSION_;
|
||||
export const version: string = _VERSION_;
|
||||
export const instanceName = siteName === "Firefish" ? host : siteName;
|
||||
export const ui = localStorage.getItem("ui");
|
||||
export const debug = localStorage.getItem("debug") === "true";
|
||||
|
|
|
@ -22,7 +22,7 @@ const apiClient = new firefishApi.APIClient({
|
|||
|
||||
export const api = ((
|
||||
endpoint: string,
|
||||
data: Record<string, any> = {},
|
||||
data: Record<string, unknown> = {},
|
||||
token?: string | null | undefined,
|
||||
useToken = true,
|
||||
) => {
|
||||
|
@ -174,13 +174,14 @@ export function promiseDialog<T>(
|
|||
}
|
||||
|
||||
let popupIdCount = 0;
|
||||
export const popups = ref<
|
||||
{
|
||||
id: number;
|
||||
component: Component;
|
||||
props: Record<string, unknown>;
|
||||
}[]
|
||||
>([]);
|
||||
|
||||
type PopupType = {
|
||||
id: number;
|
||||
component: Component;
|
||||
props: Record<string, unknown>;
|
||||
events: Record<string, unknown>;
|
||||
};
|
||||
export const popups = ref<PopupType[]>([]);
|
||||
|
||||
const zIndexes = {
|
||||
low: 1000000,
|
||||
|
@ -922,18 +923,27 @@ export function contextMenu(
|
|||
});
|
||||
}
|
||||
|
||||
export function post(props: Record<string, any> = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
export function post(
|
||||
props: InstanceType<typeof MkPostFormDialog>["$props"] = {},
|
||||
onClosed?: () => void,
|
||||
) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
// NOTE: MkPostFormDialogをdynamic importするとiOSでテキストエリアに自動フォーカスできない
|
||||
// NOTE: ただ、dynamic importしない場合、MkPostFormDialogインスタンスが使いまわされ、
|
||||
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
|
||||
// 複数のpost formを開いたときに場合によってはエラーになる
|
||||
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
|
||||
let dispose;
|
||||
// NOTE: Text area cannot be auto-focused on iOS when dynamically importing MkPostFormDialog
|
||||
// NOTE: However, if you do not dynamically import, the MkPostFormDialog instance will be reused,
|
||||
// Due to the effect that Vue internally creates a property called __props on the passed component,
|
||||
// Sometimes an error occurs when opening multiple post forms
|
||||
// Of course, opening multiple post forms is itself a bug on Misskey's side.
|
||||
let dispose: () => void;
|
||||
popup(MkPostFormDialog, props, {
|
||||
closed: () => {
|
||||
resolve();
|
||||
dispose();
|
||||
onClosed?.();
|
||||
},
|
||||
}).then((res) => {
|
||||
dispose = res.dispose;
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { Virtual } from "swiper/modules";
|
||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import type { Swiper as SwiperType } from "swiper/types";
|
||||
import XEmojis from "./about.emojis.vue";
|
||||
import XFederation from "./about.federation.vue";
|
||||
import { host, version } from "@/config";
|
||||
|
@ -294,19 +295,19 @@ watch(iconSrc, (newValue, oldValue) => {
|
|||
}
|
||||
});
|
||||
|
||||
let swiperRef = null;
|
||||
let swiperRef: SwiperType | null = null;
|
||||
|
||||
function setSwiperRef(swiper) {
|
||||
function setSwiperRef(swiper: SwiperType) {
|
||||
swiperRef = swiper;
|
||||
syncSlide(tabs.indexOf(tab.value));
|
||||
}
|
||||
|
||||
function onSlideChange() {
|
||||
tab.value = tabs[swiperRef.activeIndex];
|
||||
tab.value = tabs[swiperRef!.activeIndex];
|
||||
}
|
||||
|
||||
function syncSlide(index) {
|
||||
swiperRef.slideTo(index);
|
||||
function syncSlide(index: number) {
|
||||
swiperRef!.slideTo(index);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -94,14 +94,16 @@
|
|||
import { computed, ref } from "vue";
|
||||
|
||||
import MkSelect from "@/components/form/select.vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import XAbuseReport from "@/components/MkAbuseReport.vue";
|
||||
import { i18n } from "@/i18n";
|
||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||
import icon from "@/scripts/icon";
|
||||
import type { entities } from "firefish-js";
|
||||
|
||||
const reports = ref<InstanceType<typeof MkPagination>>();
|
||||
const reports = ref<MkPaginationType<typeof pagination.endpoint> | null>(null);
|
||||
|
||||
const state = ref("unresolved");
|
||||
const reporterOrigin = ref<entities.OriginType>("combined");
|
||||
|
|
|
@ -153,7 +153,9 @@
|
|||
import { computed, defineAsyncComponent, ref } from "vue";
|
||||
import MkButton from "@/components/MkButton.vue";
|
||||
import MkInput from "@/components/form/input.vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import MkSwitch from "@/components/form/switch.vue";
|
||||
import FormSplit from "@/components/form/split.vue";
|
||||
import { selectFile, selectFiles } from "@/scripts/select-file";
|
||||
|
@ -162,7 +164,8 @@ import { i18n } from "@/i18n";
|
|||
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const emojisPaginationComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const emojisPaginationComponent =
|
||||
ref<MkPaginationType<"admin/emoji/list"> | null>(null);
|
||||
|
||||
const tab = ref("local");
|
||||
const query = ref(null);
|
||||
|
|
|
@ -126,7 +126,9 @@
|
|||
import { computed, ref } from "vue";
|
||||
import MkInput from "@/components/form/input.vue";
|
||||
import MkSelect from "@/components/form/select.vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import * as os from "@/os";
|
||||
import { lookupUser } from "@/scripts/lookup-user";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -134,7 +136,9 @@ import { definePageMetadata } from "@/scripts/page-metadata";
|
|||
import MkUserCardMini from "@/components/MkUserCardMini.vue";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const paginationComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
const sort = ref("+createdAt");
|
||||
const state = ref("all");
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, ref } from "vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import type { MkPaginationType } from "@/components/MkPagination.vue";
|
||||
import MkButton from "@/components/MkButton.vue";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -66,7 +67,7 @@ const pagination = {
|
|||
limit: 10,
|
||||
};
|
||||
|
||||
const paginationEl = ref<InstanceType<typeof MkPagination>>();
|
||||
const paginationEl = ref<MkPaginationType<"announcements"> | null>(null);
|
||||
function read(id: string) {
|
||||
if (!paginationEl.value) return;
|
||||
paginationEl.value.updateItem(id, (announcement) => {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import type { MkPaginationType } from "@/components/MkPagination.vue";
|
||||
import XNote from "@/components/MkNote.vue";
|
||||
import XList from "@/components/MkDateSeparatedList.vue";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -48,7 +49,9 @@ const pagination = {
|
|||
limit: 10,
|
||||
};
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
definePageMetadata({
|
||||
title: i18n.ts.favorites,
|
||||
|
|
|
@ -66,14 +66,17 @@
|
|||
import { computed, ref } from "vue";
|
||||
import { acct } from "firefish-js";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import type { MkPaginationType } from "@/components/MkPagination.vue";
|
||||
import { userPage } from "@/filters/user";
|
||||
import * as os from "@/os";
|
||||
// import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||
import { me } from "@/me";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const paginationComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
const pagination = {
|
||||
endpoint: "following/requests/sent" as const,
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
import { computed, ref } from "vue";
|
||||
import { acct } from "firefish-js";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import type { MkPaginationType } from "@/components/MkPagination.vue";
|
||||
import { userPage } from "@/filters/user";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -92,7 +93,9 @@ import { definePageMetadata } from "@/scripts/page-metadata";
|
|||
import { me } from "@/me";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const paginationComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const paginationComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
const pagination = {
|
||||
endpoint: "following/requests/list" as const,
|
||||
|
@ -102,13 +105,13 @@ const pagination = {
|
|||
|
||||
function accept(user) {
|
||||
os.api("following/requests/accept", { userId: user.id }).then(() => {
|
||||
paginationComponent.value.reload();
|
||||
paginationComponent.value!.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function reject(user) {
|
||||
os.api("following/requests/reject", { userId: user.id }).then(() => {
|
||||
paginationComponent.value.reload();
|
||||
paginationComponent.value!.reload();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ import { acct } from "firefish-js";
|
|||
import XMessage from "./messaging-room.message.vue";
|
||||
import XForm from "./messaging-room.form.vue";
|
||||
import XList from "@/components/MkDateSeparatedList.vue";
|
||||
import type { Paging } from "@/components/MkPagination.vue";
|
||||
import type { MkPaginationType, Paging } from "@/components/MkPagination.vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import {
|
||||
isBottomVisible,
|
||||
|
@ -136,7 +136,9 @@ const stream = useStream();
|
|||
|
||||
const rootEl = ref<HTMLDivElement>();
|
||||
const formEl = ref<InstanceType<typeof XForm>>();
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<"messaging/messages"> | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const fetching = ref(true);
|
||||
const user = ref<entities.UserDetailed | null>(null);
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onActivated, onDeactivated, ref } from "vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, { MkPaginationType } from "@/components/MkPagination.vue";
|
||||
import MkButton from "@/components/MkButton.vue";
|
||||
import MkInfo from "@/components/MkInfo.vue";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -70,7 +70,7 @@ const headerActions = computed(() => []);
|
|||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
const list = ref<typeof MkPagination | null>(null);
|
||||
const list = ref<MkPaginationType<typeof pagination.endpoint> | null>(null);
|
||||
|
||||
let isCached = false;
|
||||
let refreshTimer: number | null = null;
|
||||
|
|
|
@ -40,7 +40,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import MkInfo from "@/components/MkInfo.vue";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -52,7 +54,9 @@ const pagination = {
|
|||
limit: 10,
|
||||
};
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
async function create() {
|
||||
const { canceled, result } = await os.form(i18n.ts.createNewClip, {
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import MkButton from "@/components/MkButton.vue";
|
||||
import MkAvatars from "@/components/MkAvatars.vue";
|
||||
import MkInfo from "@/components/MkInfo.vue";
|
||||
|
@ -53,7 +55,9 @@ import { i18n } from "@/i18n";
|
|||
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
const pagination = {
|
||||
endpoint: "users/lists/list" as const,
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import MkPagination from "@/components/MkPagination.vue";
|
||||
import MkPagination, {
|
||||
type MkPaginationType,
|
||||
} from "@/components/MkPagination.vue";
|
||||
import { api } from "@/os";
|
||||
import XList from "@/components/MkDateSeparatedList.vue";
|
||||
import XNote from "@/components/MkNote.vue";
|
||||
|
@ -43,7 +45,9 @@ import { definePageMetadata } from "@/scripts/page-metadata";
|
|||
import icon from "@/scripts/icon";
|
||||
import type { entities } from "firefish-js";
|
||||
|
||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
|
||||
const pagingComponent = ref<MkPaginationType<
|
||||
typeof pagination.endpoint
|
||||
> | null>(null);
|
||||
|
||||
const props = defineProps<{
|
||||
noteId: string;
|
||||
|
|
|
@ -89,8 +89,9 @@ const usersPagination = {
|
|||
endpoint: "users/search" as const,
|
||||
limit: 10,
|
||||
params: computed(() => ({
|
||||
query: props.query,
|
||||
origin: "combined",
|
||||
// FIXME: query is necessary for user search
|
||||
query: props.query!,
|
||||
origin: "combined" as const,
|
||||
})),
|
||||
};
|
||||
|
||||
|
|
|
@ -13,16 +13,17 @@ import { getUserMenu } from "@/scripts/get-user-menu";
|
|||
import icon from "@/scripts/icon";
|
||||
import { useRouter } from "@/router";
|
||||
import { notePage } from "@/filters/note";
|
||||
import type { NoteTranslation } from "@/types/note";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
export function getNoteMenu(props: {
|
||||
note: entities.Note;
|
||||
menuButton: Ref<HTMLElement | undefined>;
|
||||
translation: Ref<any>;
|
||||
translation: Ref<NoteTranslation | null>;
|
||||
translating: Ref<boolean>;
|
||||
isDeleted: Ref<boolean>;
|
||||
currentClipPage?: Ref<entities.Clip>;
|
||||
currentClipPage?: Ref<entities.Clip> | null;
|
||||
}) {
|
||||
const isRenote =
|
||||
props.note.renote != null &&
|
||||
|
|
|
@ -6,7 +6,7 @@ import { isSignedIn, me } from "@/me";
|
|||
import * as os from "@/os";
|
||||
|
||||
export function useNoteCapture(props: {
|
||||
rootEl: Ref<HTMLElement>;
|
||||
rootEl: Ref<HTMLElement | null>;
|
||||
note: Ref<entities.Note>;
|
||||
isDeletedRef: Ref<boolean>;
|
||||
}) {
|
||||
|
|
|
@ -3,11 +3,24 @@ import { isSignedIn } from "./me";
|
|||
import { Storage } from "./pizzax";
|
||||
import type { NoteVisibility } from "@/types/note";
|
||||
|
||||
export const postFormActions = [];
|
||||
export const userActions = [];
|
||||
export const noteActions = [];
|
||||
export const noteViewInterruptors = [];
|
||||
export const notePostInterruptors = [];
|
||||
export const postFormActions: {
|
||||
title: string;
|
||||
handler: (note: entities.Note) => void | Promise<void>;
|
||||
}[] = [];
|
||||
export const userActions: {
|
||||
title: string;
|
||||
handler: (note: entities.Note) => void | Promise<void>;
|
||||
}[] = [];
|
||||
export const noteActions: {
|
||||
title: string;
|
||||
handler: (note: entities.Note) => void | Promise<void>;
|
||||
}[] = [];
|
||||
export const noteViewInterruptors: {
|
||||
handler: (note: entities.Note) => Promise<entities.Note>;
|
||||
}[] = [];
|
||||
export const notePostInterruptors: {
|
||||
handler: (note: entities.Note) => Promise<entities.Note>;
|
||||
}[] = [];
|
||||
|
||||
const menuOptions = [
|
||||
"notifications",
|
||||
|
@ -453,6 +466,7 @@ import darkTheme from "@/themes/d-rosepine.json5";
|
|||
* Storage for configuration information that does not need to be constantly loaded into memory (non-reactive)
|
||||
*/
|
||||
import lightTheme from "@/themes/l-rosepinedawn.json5";
|
||||
import { entities } from "firefish-js";
|
||||
|
||||
export class ColdDeviceStorage {
|
||||
public static default = {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
import type { noteVisibilities } from "firefish-js";
|
||||
|
||||
export type NoteVisibility = (typeof noteVisibilities)[number] | "private";
|
||||
|
||||
export type NoteTranslation = {
|
||||
sourceLang: string;
|
||||
text: string;
|
||||
};
|
||||
|
|
|
@ -36,6 +36,7 @@ import type {
|
|||
UserDetailed,
|
||||
UserGroup,
|
||||
UserList,
|
||||
UserLite,
|
||||
UserSorting,
|
||||
} from "./entities";
|
||||
|
||||
|
@ -686,7 +687,14 @@ export type Endpoints = {
|
|||
res: Note[];
|
||||
};
|
||||
"notes/clips": { req: TODO; res: TODO };
|
||||
"notes/conversation": { req: TODO; res: TODO };
|
||||
"notes/conversation": {
|
||||
req: {
|
||||
noteId: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
};
|
||||
res: Note[];
|
||||
};
|
||||
"notes/create": {
|
||||
req: NoteSubmitReq;
|
||||
res: { createdNote: Note };
|
||||
|
@ -789,7 +797,24 @@ export type Endpoints = {
|
|||
res: Note[];
|
||||
};
|
||||
"notes/search-by-tag": { req: TODO; res: TODO };
|
||||
"notes/search": { req: TODO; res: TODO };
|
||||
"notes/search": {
|
||||
req: {
|
||||
query: string;
|
||||
sinceId?: string;
|
||||
untilId?: string;
|
||||
sinceDate?: number;
|
||||
untilDate?: number;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
host?: string;
|
||||
userId?: string;
|
||||
withFiles?: boolean;
|
||||
searchCwAndAlt?: boolean;
|
||||
channelId?: string;
|
||||
order?: "chronological" | "relevancy";
|
||||
};
|
||||
res: Note[];
|
||||
};
|
||||
"notes/show": { req: { noteId: Note["id"] }; res: Note };
|
||||
"notes/state": { req: TODO; res: TODO };
|
||||
"notes/timeline": {
|
||||
|
@ -802,6 +827,16 @@ export type Endpoints = {
|
|||
};
|
||||
res: Note[];
|
||||
};
|
||||
"notes/translate": {
|
||||
req: {
|
||||
noteId: string;
|
||||
targetLang: string;
|
||||
};
|
||||
res: {
|
||||
sourceLang: string;
|
||||
text: string;
|
||||
};
|
||||
};
|
||||
"notes/unrenote": { req: { noteId: Note["id"] }; res: null };
|
||||
"notes/user-list-timeline": {
|
||||
req: {
|
||||
|
@ -972,7 +1007,16 @@ export type Endpoints = {
|
|||
"users/relation": { req: TODO; res: TODO };
|
||||
"users/report-abuse": { req: TODO; res: TODO };
|
||||
"users/search-by-username-and-host": { req: TODO; res: TODO };
|
||||
"users/search": { req: TODO; res: TODO };
|
||||
"users/search": {
|
||||
req: {
|
||||
query: string;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
origin?: "local" | "remote" | "combined";
|
||||
detail?: true; // FIXME: when false, returns UserLite
|
||||
};
|
||||
res: UserDetailed[];
|
||||
};
|
||||
"users/show": {
|
||||
req: ShowUserReq | { userIds: User["id"][] };
|
||||
res: {
|
||||
|
|
|
@ -19,14 +19,7 @@ export type UserLite = {
|
|||
alsoKnownAs: string[];
|
||||
movedToUri: any;
|
||||
emojis: EmojiLite[];
|
||||
instance?: {
|
||||
name: Instance["name"];
|
||||
softwareName: Instance["softwareName"];
|
||||
softwareVersion: Instance["softwareVersion"];
|
||||
iconUrl: Instance["iconUrl"];
|
||||
faviconUrl: Instance["faviconUrl"];
|
||||
themeColor: Instance["themeColor"];
|
||||
};
|
||||
instance?: InstanceLite;
|
||||
};
|
||||
|
||||
export type UserDetailed = UserLite & {
|
||||
|
@ -556,6 +549,15 @@ export type Blocking = {
|
|||
blockee: UserDetailed;
|
||||
};
|
||||
|
||||
export type InstanceLite = {
|
||||
name: Instance["name"];
|
||||
softwareName: Instance["softwareName"];
|
||||
softwareVersion: Instance["softwareVersion"];
|
||||
iconUrl: Instance["iconUrl"];
|
||||
faviconUrl: Instance["faviconUrl"];
|
||||
themeColor: Instance["themeColor"];
|
||||
};
|
||||
|
||||
export type Instance = {
|
||||
id: ID;
|
||||
caughtAt: DateString;
|
||||
|
|
Loading…
Reference in a new issue