Merge branch 'develop' into feat/drive-file-usage-hints
This commit is contained in:
commit
4d34e14dd8
28 changed files with 129 additions and 169 deletions
|
@ -5,6 +5,10 @@ Critical security updates are indicated by the :warning: icon.
|
|||
- Server administrators should check [notice-for-admins.md](./notice-for-admins.md) as well.
|
||||
- Third-party client/bot developers may want to check [api-change.md](./api-change.md) as well.
|
||||
|
||||
## [v20240421](https://firefish.dev/firefish/firefish/-/merge_requests/10756/commits)
|
||||
|
||||
- Fix bugs
|
||||
|
||||
## [v20240413](https://firefish.dev/firefish/firefish/-/merge_requests/10741/commits)
|
||||
|
||||
- Add "Media" tab to user page
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "firefish",
|
||||
"version": "20240413",
|
||||
"version": "20240421",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://firefish.dev/firefish/firefish.git"
|
||||
|
|
|
@ -17,7 +17,7 @@ regenerate-entities:
|
|||
attribute=$$(printf 'cfg_attr(feature = "napi", napi_derive::napi(object, js_name = "%s", use_nullable = true))' "$${jsname}"); \
|
||||
sed -i "s/NAPI_EXTRA_ATTR_PLACEHOLDER/$${attribute}/" "$${file}"; \
|
||||
done
|
||||
sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi)]/' \
|
||||
sed -i 's/#\[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum)\]/#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]\n#[cfg_attr(not(feature = "napi"), derive(Clone))]\n#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]/' \
|
||||
src/model/entity/sea_orm_active_enums.rs
|
||||
cargo fmt --all --
|
||||
|
||||
|
|
132
packages/backend-rs/index.d.ts
vendored
132
packages/backend-rs/index.d.ts
vendored
|
@ -772,81 +772,81 @@ export interface ReplyMuting {
|
|||
muteeId: string
|
||||
muterId: string
|
||||
}
|
||||
export const enum AntennaSrcEnum {
|
||||
All = 0,
|
||||
Group = 1,
|
||||
Home = 2,
|
||||
Instances = 3,
|
||||
List = 4,
|
||||
Users = 5
|
||||
export enum AntennaSrcEnum {
|
||||
All = 'all',
|
||||
Group = 'group',
|
||||
Home = 'home',
|
||||
Instances = 'instances',
|
||||
List = 'list',
|
||||
Users = 'users'
|
||||
}
|
||||
export const enum MutedNoteReasonEnum {
|
||||
Manual = 0,
|
||||
Other = 1,
|
||||
Spam = 2,
|
||||
Word = 3
|
||||
export enum MutedNoteReasonEnum {
|
||||
Manual = 'manual',
|
||||
Other = 'other',
|
||||
Spam = 'spam',
|
||||
Word = 'word'
|
||||
}
|
||||
export const enum NoteVisibilityEnum {
|
||||
Followers = 0,
|
||||
Hidden = 1,
|
||||
Home = 2,
|
||||
Public = 3,
|
||||
Specified = 4
|
||||
export enum NoteVisibilityEnum {
|
||||
Followers = 'followers',
|
||||
Hidden = 'hidden',
|
||||
Home = 'home',
|
||||
Public = 'public',
|
||||
Specified = 'specified'
|
||||
}
|
||||
export const enum NotificationTypeEnum {
|
||||
App = 0,
|
||||
Follow = 1,
|
||||
FollowRequestAccepted = 2,
|
||||
GroupInvited = 3,
|
||||
Mention = 4,
|
||||
PollEnded = 5,
|
||||
PollVote = 6,
|
||||
Quote = 7,
|
||||
Reaction = 8,
|
||||
ReceiveFollowRequest = 9,
|
||||
Renote = 10,
|
||||
Reply = 11
|
||||
export enum NotificationTypeEnum {
|
||||
App = 'app',
|
||||
Follow = 'follow',
|
||||
FollowRequestAccepted = 'followRequestAccepted',
|
||||
GroupInvited = 'groupInvited',
|
||||
Mention = 'mention',
|
||||
PollEnded = 'pollEnded',
|
||||
PollVote = 'pollVote',
|
||||
Quote = 'quote',
|
||||
Reaction = 'reaction',
|
||||
ReceiveFollowRequest = 'receiveFollowRequest',
|
||||
Renote = 'renote',
|
||||
Reply = 'reply'
|
||||
}
|
||||
export const enum PageVisibilityEnum {
|
||||
Followers = 0,
|
||||
Public = 1,
|
||||
Specified = 2
|
||||
export enum PageVisibilityEnum {
|
||||
Followers = 'followers',
|
||||
Public = 'public',
|
||||
Specified = 'specified'
|
||||
}
|
||||
export const enum PollNotevisibilityEnum {
|
||||
Followers = 0,
|
||||
Home = 1,
|
||||
Public = 2,
|
||||
Specified = 3
|
||||
export enum PollNotevisibilityEnum {
|
||||
Followers = 'followers',
|
||||
Home = 'home',
|
||||
Public = 'public',
|
||||
Specified = 'specified'
|
||||
}
|
||||
export const enum RelayStatusEnum {
|
||||
Accepted = 0,
|
||||
Rejected = 1,
|
||||
Requesting = 2
|
||||
export enum RelayStatusEnum {
|
||||
Accepted = 'accepted',
|
||||
Rejected = 'rejected',
|
||||
Requesting = 'requesting'
|
||||
}
|
||||
export const enum UserEmojimodpermEnum {
|
||||
Add = 0,
|
||||
Full = 1,
|
||||
Mod = 2,
|
||||
Unauthorized = 3
|
||||
export enum UserEmojimodpermEnum {
|
||||
Add = 'add',
|
||||
Full = 'full',
|
||||
Mod = 'mod',
|
||||
Unauthorized = 'unauthorized'
|
||||
}
|
||||
export const enum UserProfileFfvisibilityEnum {
|
||||
Followers = 0,
|
||||
Private = 1,
|
||||
Public = 2
|
||||
export enum UserProfileFfvisibilityEnum {
|
||||
Followers = 'followers',
|
||||
Private = 'private',
|
||||
Public = 'public'
|
||||
}
|
||||
export const enum UserProfileMutingnotificationtypesEnum {
|
||||
App = 0,
|
||||
Follow = 1,
|
||||
FollowRequestAccepted = 2,
|
||||
GroupInvited = 3,
|
||||
Mention = 4,
|
||||
PollEnded = 5,
|
||||
PollVote = 6,
|
||||
Quote = 7,
|
||||
Reaction = 8,
|
||||
ReceiveFollowRequest = 9,
|
||||
Renote = 10,
|
||||
Reply = 11
|
||||
export enum UserProfileMutingnotificationtypesEnum {
|
||||
App = 'app',
|
||||
Follow = 'follow',
|
||||
FollowRequestAccepted = 'followRequestAccepted',
|
||||
GroupInvited = 'groupInvited',
|
||||
Mention = 'mention',
|
||||
PollEnded = 'pollEnded',
|
||||
PollVote = 'pollVote',
|
||||
Quote = 'quote',
|
||||
Reaction = 'reaction',
|
||||
ReceiveFollowRequest = 'receiveFollowRequest',
|
||||
Renote = 'renote',
|
||||
Reply = 'reply'
|
||||
}
|
||||
export interface Signin {
|
||||
id: string
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
},
|
||||
"scripts": {
|
||||
"artifacts": "napi artifacts",
|
||||
"build": "napi build --features napi --platform --release ./built/",
|
||||
"build:debug": "napi build --features napi --platform ./built/",
|
||||
"build": "napi build --features napi --no-const-enum --platform --release ./built/",
|
||||
"build:debug": "napi build --features napi --no-const-enum --platform ./built/",
|
||||
"prepublishOnly": "napi prepublish -t npm",
|
||||
"test": "pnpm run cargo:test && pnpm run build:debug && ava",
|
||||
"universal": "napi universal",
|
||||
|
|
|
@ -4,7 +4,7 @@ use sea_orm::entity::prelude::*;
|
|||
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "antenna_src_enum")]
|
||||
pub enum AntennaSrcEnum {
|
||||
#[sea_orm(string_value = "all")]
|
||||
|
@ -22,7 +22,7 @@ pub enum AntennaSrcEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -40,7 +40,7 @@ pub enum MutedNoteReasonEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -60,7 +60,7 @@ pub enum NoteVisibilityEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -94,7 +94,7 @@ pub enum NotificationTypeEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -110,7 +110,7 @@ pub enum PageVisibilityEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -128,7 +128,7 @@ pub enum PollNotevisibilityEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "relay_status_enum")]
|
||||
pub enum RelayStatusEnum {
|
||||
#[sea_orm(string_value = "accepted")]
|
||||
|
@ -140,7 +140,7 @@ pub enum RelayStatusEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -158,7 +158,7 @@ pub enum UserEmojimodpermEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
@ -174,7 +174,7 @@ pub enum UserProfileFfvisibilityEnum {
|
|||
}
|
||||
#[derive(Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum)]
|
||||
#[cfg_attr(not(feature = "napi"), derive(Clone))]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi)]
|
||||
#[cfg_attr(feature = "napi", napi_derive::napi(string_enum = "camelCase"))]
|
||||
#[sea_orm(
|
||||
rs_type = "String",
|
||||
db_type = "Enum",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { redisClient } from "@/db/redis.js";
|
||||
import { encode, decode } from "msgpackr";
|
||||
import { ChainableCommander } from "ioredis";
|
||||
import type { ChainableCommander } from "ioredis";
|
||||
|
||||
export class Cache<T> {
|
||||
private ttl: number;
|
||||
|
|
|
@ -34,7 +34,7 @@ export function initialize<T>(name: string, limitPerSec = -1) {
|
|||
function apBackoff(attemptsMade: number, err: Error) {
|
||||
const baseDelay = 60 * 1000; // 1min
|
||||
const maxBackoff = 8 * 60 * 60 * 1000; // 8hours
|
||||
let backoff = (Math.pow(2, attemptsMade) - 1) * baseDelay;
|
||||
let backoff = (2 ** attemptsMade - 1) * baseDelay;
|
||||
backoff = Math.min(backoff, maxBackoff);
|
||||
backoff += Math.round(backoff * Math.random() * 0.2);
|
||||
return backoff;
|
||||
|
|
|
@ -32,7 +32,7 @@ import Followers from "./activitypub/followers.js";
|
|||
import Outbox, { packActivity } from "./activitypub/outbox.js";
|
||||
import { serverLogger } from "./index.js";
|
||||
import config from "@/config/index.js";
|
||||
import Koa from "koa";
|
||||
import type Koa from "koa";
|
||||
import * as crypto from "node:crypto";
|
||||
import { inspect } from "node:util";
|
||||
import type { IActivity } from "@/remote/activitypub/type.js";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type * as http from "node:http";
|
||||
import { EventEmitter } from "events";
|
||||
import type { ParsedUrlQuery } from "querystring";
|
||||
import { EventEmitter } from "node:events";
|
||||
import type { ParsedUrlQuery } from "node:querystring";
|
||||
import * as websocket from "websocket";
|
||||
|
||||
import { subscriber as redisClient } from "@/db/redis.js";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Readable, ReadableOptions } from "node:stream";
|
||||
import { Readable, type ReadableOptions } from "node:stream";
|
||||
import { Buffer } from "node:buffer";
|
||||
import * as fs from "node:fs";
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@ app.use(async (ctx, next) => {
|
|||
const url = decodeURI(ctx.path);
|
||||
|
||||
if (url === bullBoardPath || url.startsWith(`${bullBoardPath}/`)) {
|
||||
if (!url.startsWith(`${bullBoardPath}/static/`)) {
|
||||
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
|
||||
}
|
||||
|
||||
const token = ctx.cookies.get("token");
|
||||
if (token == null) {
|
||||
ctx.status = 401;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import type { KVs } from "../core.js";
|
||||
import Chart from "../core.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import { name, schema } from "./entities/active-users.js";
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Window } from "happy-dom";
|
||||
import type { HTMLAnchorElement, HTMLLinkElement } from "happy-dom";
|
||||
import config from "@/config/index.js";
|
||||
|
||||
async function getRelMeLinks(url: string): Promise<string[]> {
|
||||
|
|
|
@ -28,9 +28,9 @@ export default class Logger {
|
|||
|
||||
if (config.syslog) {
|
||||
this.syslogClient = new SyslogPro.RFC5424({
|
||||
applacationName: "Firefish",
|
||||
applicationName: "Firefish",
|
||||
timestamp: true,
|
||||
encludeStructuredData: true,
|
||||
includeStructuredData: true,
|
||||
color: true,
|
||||
extendedColor: true,
|
||||
server: {
|
||||
|
@ -144,12 +144,12 @@ export default class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
// Used when the process can't continue (fatal error)
|
||||
public error(
|
||||
x: string | Error,
|
||||
data?: Record<string, any> | null,
|
||||
important = false,
|
||||
): void {
|
||||
// 実行を継続できない状況で使う
|
||||
if (x instanceof Error) {
|
||||
data = data || {};
|
||||
data.e = x;
|
||||
|
@ -166,30 +166,30 @@ export default class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
// Used when the process can continue but some action should be taken
|
||||
public warn(
|
||||
message: string,
|
||||
data?: Record<string, any> | null,
|
||||
important = false,
|
||||
): void {
|
||||
// 実行を継続できるが改善すべき状況で使う
|
||||
this.log("warning", message, data, important);
|
||||
}
|
||||
|
||||
// Used when something is successful
|
||||
public succ(
|
||||
message: string,
|
||||
data?: Record<string, any> | null,
|
||||
important = false,
|
||||
): void {
|
||||
// 何かに成功した状況で使う
|
||||
this.log("success", message, data, important);
|
||||
}
|
||||
|
||||
// Used for debugging (information necessary for developers but unnecessary for users)
|
||||
public debug(
|
||||
message: string,
|
||||
data?: Record<string, any> | null,
|
||||
important = false,
|
||||
): void {
|
||||
// Used for debugging (information necessary for developers but unnecessary for users)
|
||||
// Fixed if statement is ignored when logLevel includes debug
|
||||
if (
|
||||
config.logLevel?.includes("debug") ||
|
||||
|
@ -200,12 +200,12 @@ export default class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
// Other generic logs
|
||||
public info(
|
||||
message: string,
|
||||
data?: Record<string, any> | null,
|
||||
important = false,
|
||||
): void {
|
||||
// それ以外
|
||||
this.log("info", message, data, important);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
import { publishMainStream } from "@/services/stream.js";
|
||||
import type { Note } from "@/models/entities/note.js";
|
||||
import type { User } from "@/models/entities/user.js";
|
||||
import {
|
||||
NoteUnreads,
|
||||
Users,
|
||||
Followings,
|
||||
ChannelFollowings,
|
||||
} from "@/models/index.js";
|
||||
import { NoteUnreads, Followings, ChannelFollowings } from "@/models/index.js";
|
||||
import { Not, IsNull, In } from "typeorm";
|
||||
import type { Channel } from "@/models/entities/channel.js";
|
||||
import { readNotificationByQuery } from "@/server/api/common/read-notification.js";
|
||||
|
@ -120,34 +115,4 @@ export default async function (
|
|||
]),
|
||||
});
|
||||
}
|
||||
|
||||
// if (readAntennaNotes.length > 0) {
|
||||
// await AntennaNotes.update(
|
||||
// {
|
||||
// antennaId: In(myAntennas.map((a) => a.id)),
|
||||
// noteId: In(readAntennaNotes.map((n) => n.id)),
|
||||
// },
|
||||
// {
|
||||
// read: true,
|
||||
// },
|
||||
// );
|
||||
|
||||
// // TODO: まとめてクエリしたい
|
||||
// for (const antenna of myAntennas) {
|
||||
// const count = await AntennaNotes.countBy({
|
||||
// antennaId: antenna.id,
|
||||
// read: false,
|
||||
// });
|
||||
|
||||
// if (count === 0) {
|
||||
// publishMainStream(userId, "readAntenna", antenna);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Users.getHasUnreadAntenna(userId).then((unread) => {
|
||||
// if (!unread) {
|
||||
// publishMainStream(userId, "readAllAntennas");
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -28,11 +28,10 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from "vue";
|
||||
import MkTooltip from "./MkTooltip.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
showing: Ref<boolean>;
|
||||
showing: boolean;
|
||||
x: number;
|
||||
y: number;
|
||||
title?: string;
|
||||
|
|
|
@ -231,15 +231,9 @@ const unicodeEmojiSkinToneLabels = [
|
|||
i18n.ts._skinTones?.dark ?? "Dark",
|
||||
];
|
||||
|
||||
const size = computed(() =>
|
||||
props.asReactionPicker ? reactionPickerSize.value : 1,
|
||||
);
|
||||
const width = computed(() =>
|
||||
props.asReactionPicker ? reactionPickerWidth.value : 3,
|
||||
);
|
||||
const height = computed(() =>
|
||||
props.asReactionPicker ? reactionPickerHeight.value : 2,
|
||||
);
|
||||
const size = reactionPickerSize;
|
||||
const width = reactionPickerWidth;
|
||||
const height = reactionPickerHeight;
|
||||
const customEmojiCategories = emojiCategories;
|
||||
const customEmojis = instance.emojis;
|
||||
const q = ref<string | null>(null);
|
||||
|
|
|
@ -39,7 +39,7 @@ import { defaultStore } from "@/store";
|
|||
withDefaults(
|
||||
defineProps<{
|
||||
manualShowing?: boolean | null;
|
||||
src?: HTMLElement;
|
||||
src?: HTMLElement | null;
|
||||
showPinned?: boolean;
|
||||
asReactionPicker?: boolean;
|
||||
}>(),
|
||||
|
|
|
@ -42,7 +42,7 @@ useTooltip(el, (showing) => {
|
|||
os.popup(
|
||||
defineAsyncComponent(() => import("@/components/MkUrlPreviewPopup.vue")),
|
||||
{
|
||||
showing: showing.value,
|
||||
showing,
|
||||
url: props.url,
|
||||
source: el.value,
|
||||
},
|
||||
|
|
|
@ -1188,7 +1188,7 @@ async function insertEmoji(ev: MouseEvent) {
|
|||
os.openEmojiPicker(
|
||||
(ev.currentTarget ?? ev.target) as HTMLElement,
|
||||
{},
|
||||
textareaEl.value,
|
||||
textareaEl.value!,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from "vue";
|
||||
import type { entities } from "firefish-js";
|
||||
import MkTooltip from "./MkTooltip.vue";
|
||||
import XReactionIcon from "@/components/MkReactionIcon.vue";
|
||||
|
||||
defineProps<{
|
||||
showing: Ref<boolean>;
|
||||
showing: boolean;
|
||||
reaction: string;
|
||||
emojis: entities.EmojiLite[];
|
||||
targetElement: HTMLElement;
|
||||
|
|
|
@ -30,13 +30,12 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from "vue";
|
||||
import type { entities } from "firefish-js";
|
||||
import MkTooltip from "./MkTooltip.vue";
|
||||
import XReactionIcon from "@/components/MkReactionIcon.vue";
|
||||
|
||||
defineProps<{
|
||||
showing: Ref<boolean>;
|
||||
showing: boolean;
|
||||
reaction: string;
|
||||
users: entities.User[]; // TODO
|
||||
count: number;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@after-leave="emit('closed')"
|
||||
>
|
||||
<div
|
||||
v-show="unref(showing)"
|
||||
v-show="showing"
|
||||
ref="el"
|
||||
class="buebdbiu _acrylic _shadow"
|
||||
:style="{ zIndex, maxWidth: maxWidth + 'px' }"
|
||||
|
@ -19,21 +19,14 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
type MaybeRef,
|
||||
nextTick,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
ref,
|
||||
unref,
|
||||
} from "vue";
|
||||
import { nextTick, onMounted, onUnmounted, ref } from "vue";
|
||||
import * as os from "@/os";
|
||||
import { calcPopupPosition } from "@/scripts/popup-position";
|
||||
import { defaultStore } from "@/store";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
showing: MaybeRef<boolean>;
|
||||
showing: boolean;
|
||||
targetElement?: HTMLElement | null;
|
||||
x?: number;
|
||||
y?: number;
|
||||
|
|
|
@ -19,12 +19,11 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from "vue";
|
||||
import type { entities } from "firefish-js";
|
||||
import MkTooltip from "./MkTooltip.vue";
|
||||
|
||||
defineProps<{
|
||||
showing: Ref<boolean>;
|
||||
showing: boolean;
|
||||
users: entities.User[];
|
||||
count: number;
|
||||
targetElement?: HTMLElement;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
]"
|
||||
>
|
||||
<i
|
||||
v-if="unref(success)"
|
||||
v-if="success"
|
||||
:class="[$style.icon, $style.success, iconify('ph-check')]"
|
||||
></i>
|
||||
<MkLoading
|
||||
|
@ -29,16 +29,15 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { MaybeRef } from "vue";
|
||||
import { shallowRef, unref, watch } from "vue";
|
||||
import { shallowRef, watch } from "vue";
|
||||
import MkModal from "@/components/MkModal.vue";
|
||||
import iconify from "@/scripts/icon";
|
||||
|
||||
const modal = shallowRef<InstanceType<typeof MkModal>>();
|
||||
|
||||
const props = defineProps<{
|
||||
success: MaybeRef<boolean>;
|
||||
showing: MaybeRef<boolean>;
|
||||
success: boolean;
|
||||
showing: boolean;
|
||||
text?: string;
|
||||
}>();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import { EventEmitter } from "eventemitter3";
|
||||
import { type Endpoints, type entities, api as firefishApi } from "firefish-js";
|
||||
import insertTextAtCursor from "insert-text-at-cursor";
|
||||
import type { Component, Ref } from "vue";
|
||||
import type { Component, MaybeRef, Ref } from "vue";
|
||||
import { defineAsyncComponent, markRaw, ref } from "vue";
|
||||
import { i18n } from "./i18n";
|
||||
import MkDialog from "@/components/MkDialog.vue";
|
||||
|
@ -213,9 +213,13 @@ interface VueComponentConstructor<P, E> {
|
|||
|
||||
type NonArrayAble<A> = A extends Array<unknown> ? never : A;
|
||||
|
||||
type CanUseRef<T> = {
|
||||
[K in keyof T]: MaybeRef<T[K]>;
|
||||
};
|
||||
|
||||
export async function popup<Props, Emits>(
|
||||
component: VueComponentConstructor<Props, Emits>,
|
||||
props: Props,
|
||||
props: CanUseRef<Props>,
|
||||
events: Partial<NonArrayAble<NonNullable<Emits>>> = {},
|
||||
disposeEvent?: keyof Partial<NonArrayAble<NonNullable<Emits>>>,
|
||||
) {
|
||||
|
@ -240,6 +244,7 @@ export async function popup<Props, Emits>(
|
|||
id,
|
||||
};
|
||||
|
||||
// Hint: Vue will automatically resolve ref here, so it is safe to use ref in props
|
||||
popups.value.push(state);
|
||||
|
||||
return {
|
||||
|
|
|
@ -24,14 +24,14 @@ class ReactionPicker {
|
|||
},
|
||||
{
|
||||
done: (reaction) => {
|
||||
this.onChosen!(reaction);
|
||||
this.onChosen?.(reaction);
|
||||
},
|
||||
close: () => {
|
||||
this.manualShowing.value = false;
|
||||
},
|
||||
closed: () => {
|
||||
this.src.value = null;
|
||||
this.onClosed!();
|
||||
this.onClosed?.();
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue