chore: lint
This commit is contained in:
parent
97bb495636
commit
2d9d6e9fb7
60 changed files with 303 additions and 290 deletions
|
@ -1,7 +1,7 @@
|
|||
import config from "@/config/index.js";
|
||||
import {
|
||||
DB_MAX_NOTE_TEXT_LENGTH,
|
||||
DB_MAX_IMAGE_COMMENT_LENGTH,
|
||||
DB_MAX_NOTE_TEXT_LENGTH,
|
||||
} from "@/misc/hard-limits.js";
|
||||
|
||||
export const MAX_NOTE_TEXT_LENGTH = Math.min(
|
||||
|
|
2
packages/backend/src/global.d.ts
vendored
2
packages/backend/src/global.d.ts
vendored
|
@ -1,2 +1,2 @@
|
|||
// rome-ignore lint/suspicious/noExplicitAny: i have no idea
|
||||
// biome-ignore lint/suspicious/noExplicitAny: i have no idea
|
||||
type FIXME = any;
|
||||
|
|
|
@ -25,7 +25,8 @@ const assets = `${_dirname}/../../server/file/assets/`;
|
|||
const MAX_BYTE_RANGES = 10;
|
||||
|
||||
const commonReadableHandlerGenerator =
|
||||
(ctx: Koa.Context) => (e: Error): void => {
|
||||
(ctx: Koa.Context) =>
|
||||
(e: Error): void => {
|
||||
serverLogger.error(e);
|
||||
ctx.status = 500;
|
||||
ctx.set("Cache-Control", "max-age=300");
|
||||
|
|
|
@ -175,7 +175,8 @@ export default async (
|
|||
) =>
|
||||
// biome-ignore lint/suspicious/noAsyncPromiseExecutor: FIXME
|
||||
new Promise<Note>(async (res, rej) => {
|
||||
const dontFederateInitially = data.localOnly || data.visibility?.startsWith("hidden") === true;
|
||||
const dontFederateInitially =
|
||||
data.localOnly || data.visibility?.startsWith("hidden") === true;
|
||||
|
||||
// If you reply outside the channel, match the scope of the target.
|
||||
// TODO (I think it's a process that could be done on the client side, but it's server side for now.)
|
||||
|
|
|
@ -2,8 +2,8 @@ import * as assert from "assert";
|
|||
import httpSignature from "@peertube/http-signature";
|
||||
import { genRsaKeyPair } from "../src/misc/gen-key-pair.js";
|
||||
import {
|
||||
createSignedPost,
|
||||
createSignedGet,
|
||||
createSignedPost,
|
||||
} from "../src/remote/activitypub/ap-request.js";
|
||||
|
||||
export const buildParsedSignature = (
|
||||
|
|
|
@ -4,11 +4,11 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
post,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("API visibility", () => {
|
||||
|
|
|
@ -4,13 +4,13 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
post,
|
||||
react,
|
||||
uploadFile,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
uploadFile,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("API", () => {
|
||||
|
|
|
@ -4,11 +4,11 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
post,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("Block", () => {
|
||||
|
|
|
@ -2,11 +2,11 @@ process.env.NODE_ENV = "test";
|
|||
|
||||
import * as assert from "assert";
|
||||
import * as lolex from "@sinonjs/fake-timers";
|
||||
import TestChart from "../src/services/chart/charts/test.js";
|
||||
import TestGroupedChart from "../src/services/chart/charts/test-grouped.js";
|
||||
import TestUniqueChart from "../src/services/chart/charts/test-unique.js";
|
||||
import TestIntersectionChart from "../src/services/chart/charts/test-intersection.js";
|
||||
import { initDb } from "../src/db/postgre.js";
|
||||
import TestGroupedChart from "../src/services/chart/charts/test-grouped.js";
|
||||
import TestIntersectionChart from "../src/services/chart/charts/test-intersection.js";
|
||||
import TestUniqueChart from "../src/services/chart/charts/test-unique.js";
|
||||
import TestChart from "../src/services/chart/charts/test.js";
|
||||
|
||||
describe("Chart", () => {
|
||||
let testChart: TestChart;
|
||||
|
|
|
@ -5,13 +5,13 @@ import * as childProcess from "child_process";
|
|||
import * as openapi from "@redocly/openapi-core";
|
||||
import {
|
||||
async,
|
||||
startServer,
|
||||
signup,
|
||||
port,
|
||||
post,
|
||||
request,
|
||||
simpleGet,
|
||||
port,
|
||||
shutdownServer,
|
||||
signup,
|
||||
simpleGet,
|
||||
startServer,
|
||||
} from "./utils.js";
|
||||
|
||||
// Request Accept
|
||||
|
|
|
@ -4,14 +4,14 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
connectStream,
|
||||
post,
|
||||
react,
|
||||
connectStream,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
simpleGet,
|
||||
startServer,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("FF visibility", () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as assert from "assert";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { getFileInfo } from "../src/misc/get-file-info.js";
|
||||
import { async } from "./utils.js";
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import * as assert from "assert";
|
||||
import * as mfm from "mfm-js";
|
||||
|
||||
import { toHtml } from "../src/mfm/to-html.js";
|
||||
import { fromHtml } from "../src/mfm/from-html.js";
|
||||
import { toHtml } from "../src/mfm/to-html.js";
|
||||
|
||||
describe("toHtml", () => {
|
||||
it("br", () => {
|
||||
|
|
|
@ -4,12 +4,12 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
post,
|
||||
react,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
waitFire,
|
||||
} from "./utils.js";
|
||||
|
||||
|
|
|
@ -4,15 +4,15 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import { Note } from "../src/models/entities/note.js";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
post,
|
||||
uploadUrl,
|
||||
startServer,
|
||||
shutdownServer,
|
||||
initTestDb,
|
||||
api,
|
||||
async,
|
||||
initTestDb,
|
||||
post,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
uploadUrl,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("Note", () => {
|
||||
|
|
|
@ -4,13 +4,13 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import { Following } from "../src/models/entities/following.js";
|
||||
import {
|
||||
connectStream,
|
||||
signup,
|
||||
api,
|
||||
post,
|
||||
startServer,
|
||||
shutdownServer,
|
||||
connectStream,
|
||||
initTestDb,
|
||||
post,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
waitFire,
|
||||
} from "./utils.js";
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
connectStream,
|
||||
post,
|
||||
react,
|
||||
connectStream,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("Note thread mute", () => {
|
||||
|
|
|
@ -4,12 +4,12 @@ import * as assert from "assert";
|
|||
import * as childProcess from "child_process";
|
||||
import {
|
||||
async,
|
||||
signup,
|
||||
request,
|
||||
post,
|
||||
uploadUrl,
|
||||
startServer,
|
||||
request,
|
||||
shutdownServer,
|
||||
signup,
|
||||
startServer,
|
||||
uploadUrl,
|
||||
} from "./utils.js";
|
||||
|
||||
describe("users/notes", () => {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname } from "node:path";
|
||||
import * as childProcess from "child_process";
|
||||
import * as http from "node:http";
|
||||
import { SIGKILL } from "constants";
|
||||
import WebSocket from "ws";
|
||||
import * as fs from "node:fs";
|
||||
import * as http from "node:http";
|
||||
import * as path from "node:path";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import * as firefish from "firefish-js";
|
||||
import fetch from "node-fetch";
|
||||
import FormData from "form-data";
|
||||
import got from "got";
|
||||
import fetch from "node-fetch";
|
||||
import { DataSource } from "typeorm";
|
||||
import WebSocket from "ws";
|
||||
import loadConfig from "../src/config/load.js";
|
||||
import { entities } from "../src/db/postgre.js";
|
||||
import got from "got";
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { defineAsyncComponent } from "vue";
|
||||
import type * as firefish from "firefish-js";
|
||||
import { defineAsyncComponent } from "vue";
|
||||
import { i18n } from "./i18n";
|
||||
import { del, get, set } from "@/scripts/idb-proxy";
|
||||
import { apiUrl } from "@/config";
|
||||
import { alert, api, popup, popupMenu, waiting } from "@/os";
|
||||
import { reloadChannel, unisonReload } from "@/scripts/unison-reload";
|
||||
import icon from "@/scripts/icon";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import icon from "@/scripts/icon";
|
||||
import { del, get, set } from "@/scripts/idb-proxy";
|
||||
import { reloadChannel, unisonReload } from "@/scripts/unison-reload";
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
message.groupId
|
||||
? message.user
|
||||
: isMe(message)
|
||||
? message.recipient
|
||||
: message.user
|
||||
? message.recipient
|
||||
: message.user
|
||||
"
|
||||
:show-indicator="true"
|
||||
disable-link
|
||||
|
|
|
@ -327,8 +327,8 @@ async function ok() {
|
|||
const result = props.input
|
||||
? inputValue.value
|
||||
: props.select
|
||||
? selectedValue.value
|
||||
: true;
|
||||
? selectedValue.value
|
||||
: true;
|
||||
done(false, result);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
? i18n.ts.selectFiles
|
||||
: i18n.ts.selectFolders
|
||||
: type === "file"
|
||||
? i18n.ts.selectFile
|
||||
: i18n.ts.selectFolder
|
||||
? i18n.ts.selectFile
|
||||
: i18n.ts.selectFolder
|
||||
}}
|
||||
<span
|
||||
v-if="selected.length > 0"
|
||||
|
|
|
@ -88,8 +88,8 @@ const preferedModalType =
|
|||
deviceKind === "desktop" && props.src != null
|
||||
? "popup"
|
||||
: deviceKind === "smartphone"
|
||||
? "drawer"
|
||||
: "dialog";
|
||||
? "drawer"
|
||||
: "dialog";
|
||||
|
||||
const modal = ref<InstanceType<typeof MkModal>>();
|
||||
|
||||
|
|
|
@ -113,9 +113,9 @@ const url =
|
|||
props.raw || defaultStore.state.loadRawImages
|
||||
? props.media.url
|
||||
: defaultStore.state.disableShowingAnimatedImages &&
|
||||
props.media.type.startsWith("image")
|
||||
? getStaticImageUrl(props.media.thumbnailUrl)
|
||||
: props.media.thumbnailUrl;
|
||||
props.media.type.startsWith("image")
|
||||
? getStaticImageUrl(props.media.thumbnailUrl)
|
||||
: props.media.thumbnailUrl;
|
||||
|
||||
const mediaType = computed(() => {
|
||||
return props.media.type === "video/quicktime"
|
||||
|
|
|
@ -169,22 +169,22 @@ const transitionName = computed(() =>
|
|||
? useSendAnime.value
|
||||
? "send"
|
||||
: type.value === "drawer"
|
||||
? "modal-drawer"
|
||||
: type.value === "popup"
|
||||
? "modal-popup"
|
||||
: "modal"
|
||||
? "modal-drawer"
|
||||
: type.value === "popup"
|
||||
? "modal-popup"
|
||||
: "modal"
|
||||
: "",
|
||||
);
|
||||
const transitionDuration = computed(() =>
|
||||
transitionName.value === "send"
|
||||
? 400
|
||||
: transitionName.value === "modal-popup"
|
||||
? 100
|
||||
: transitionName.value === "modal"
|
||||
? 200
|
||||
: transitionName.value === "modal-drawer"
|
||||
? 200
|
||||
: 0,
|
||||
? 100
|
||||
: transitionName.value === "modal"
|
||||
? 200
|
||||
: transitionName.value === "modal-drawer"
|
||||
? 200
|
||||
: 0,
|
||||
);
|
||||
|
||||
let contentClicking = false;
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
? `${props.height}px`
|
||||
: null
|
||||
: height
|
||||
? `min(${props.height}px, 100%)`
|
||||
: '100%',
|
||||
? `min(${props.height}px, 100%)`
|
||||
: '100%',
|
||||
}"
|
||||
tabindex="-1"
|
||||
>
|
||||
|
|
|
@ -259,12 +259,12 @@ const fetchMore = async (): Promise<void> => {
|
|||
offset: offset.value,
|
||||
}
|
||||
: props.pagination.reversed
|
||||
? {
|
||||
sinceId: items.value[0].id,
|
||||
}
|
||||
: {
|
||||
untilId: items.value[items.value.length - 1].id,
|
||||
}),
|
||||
? {
|
||||
sinceId: items.value[0].id,
|
||||
}
|
||||
: {
|
||||
untilId: items.value[items.value.length - 1].id,
|
||||
}),
|
||||
})
|
||||
.then(
|
||||
(res) => {
|
||||
|
@ -320,12 +320,12 @@ const fetchMoreAhead = async (): Promise<void> => {
|
|||
offset: offset.value,
|
||||
}
|
||||
: props.pagination.reversed
|
||||
? {
|
||||
untilId: items.value[0].id,
|
||||
}
|
||||
: {
|
||||
sinceId: items.value[items.value.length - 1].id,
|
||||
}),
|
||||
? {
|
||||
untilId: items.value[0].id,
|
||||
}
|
||||
: {
|
||||
sinceId: items.value[items.value.length - 1].id,
|
||||
}),
|
||||
})
|
||||
.then(
|
||||
(res) => {
|
||||
|
|
|
@ -81,10 +81,10 @@ const timer = computed(() =>
|
|||
remaining.value >= 86400
|
||||
? "_poll.remainingDays"
|
||||
: remaining.value >= 3600
|
||||
? "_poll.remainingHours"
|
||||
: remaining.value >= 60
|
||||
? "_poll.remainingMinutes"
|
||||
: "_poll.remainingSeconds",
|
||||
? "_poll.remainingHours"
|
||||
: remaining.value >= 60
|
||||
? "_poll.remainingMinutes"
|
||||
: "_poll.remainingSeconds",
|
||||
{
|
||||
s: Math.floor(remaining.value % 60),
|
||||
m: Math.floor(remaining.value / 60) % 60,
|
||||
|
|
|
@ -171,8 +171,8 @@ function get() {
|
|||
...(expiration.value === "at"
|
||||
? { expiresAt: calcAt() }
|
||||
: expiration.value === "after"
|
||||
? { expiredAfter: calcAfter() }
|
||||
: {}),
|
||||
? { expiredAfter: calcAfter() }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@
|
|||
reply
|
||||
? 'ph-arrow-u-up-left'
|
||||
: renote
|
||||
? 'ph-quotes'
|
||||
: 'ph-paper-plane-tilt',
|
||||
? 'ph-quotes'
|
||||
: 'ph-paper-plane-tilt',
|
||||
)
|
||||
"
|
||||
></i>
|
||||
|
@ -401,10 +401,10 @@ const submitText = computed((): string => {
|
|||
return props.editId
|
||||
? i18n.ts.edit
|
||||
: props.renote
|
||||
? i18n.ts.quote
|
||||
: props.reply
|
||||
? i18n.ts.reply
|
||||
: i18n.ts.note;
|
||||
? i18n.ts.quote
|
||||
: props.reply
|
||||
? i18n.ts.reply
|
||||
: i18n.ts.note;
|
||||
});
|
||||
|
||||
const textLength = computed((): number => {
|
||||
|
@ -473,8 +473,8 @@ if (props.reply && props.reply.text != null) {
|
|||
const mention = x.host
|
||||
? `@${x.username}@${toASCII(x.host)}`
|
||||
: otherHost == null || otherHost === host
|
||||
? `@${x.username}`
|
||||
: `@${x.username}@${toASCII(otherHost)}`;
|
||||
? `@${x.username}`
|
||||
: `@${x.username}@${toASCII(otherHost)}`;
|
||||
|
||||
// 自分は除外
|
||||
if ($i.username === x.username && (x.host == null || x.host === host))
|
||||
|
@ -868,8 +868,8 @@ async function post() {
|
|||
renoteId: props.renote
|
||||
? props.renote.id
|
||||
: quoteId.value
|
||||
? quoteId.value
|
||||
: undefined,
|
||||
? quoteId.value
|
||||
: undefined,
|
||||
channelId: props.channel ? props.channel.id : undefined,
|
||||
poll: poll.value,
|
||||
cw: useCw.value ? cw.value || "" : undefined,
|
||||
|
|
|
@ -371,10 +371,10 @@ function onChangeUsername(): void {
|
|||
const err = !username.value.match(/^[a-zA-Z0-9_]+$/)
|
||||
? "invalid-format"
|
||||
: username.value.length < 1
|
||||
? "min-range"
|
||||
: username.value.length > 20
|
||||
? "max-range"
|
||||
: null;
|
||||
? "min-range"
|
||||
: username.value.length > 20
|
||||
? "max-range"
|
||||
: null;
|
||||
|
||||
if (err) {
|
||||
usernameState.value = err;
|
||||
|
@ -410,16 +410,16 @@ function onChangeEmail(): void {
|
|||
emailState.value = result.available
|
||||
? "ok"
|
||||
: result.reason === "used"
|
||||
? "unavailable:used"
|
||||
: result.reason === "format"
|
||||
? "unavailable:format"
|
||||
: result.reason === "disposable"
|
||||
? "unavailable:disposable"
|
||||
: result.reason === "mx"
|
||||
? "unavailable:mx"
|
||||
: result.reason === "smtp"
|
||||
? "unavailable:smtp"
|
||||
: "unavailable";
|
||||
? "unavailable:used"
|
||||
: result.reason === "format"
|
||||
? "unavailable:format"
|
||||
: result.reason === "disposable"
|
||||
? "unavailable:disposable"
|
||||
: result.reason === "mx"
|
||||
? "unavailable:mx"
|
||||
: result.reason === "smtp"
|
||||
? "unavailable:smtp"
|
||||
: "unavailable";
|
||||
})
|
||||
.catch(() => {
|
||||
emailState.value = "error";
|
||||
|
|
|
@ -29,11 +29,11 @@ const _time =
|
|||
props.time == null
|
||||
? NaN
|
||||
: typeof props.time === "number"
|
||||
? props.time
|
||||
: (props.time instanceof Date
|
||||
? props.time
|
||||
: new Date(props.time)
|
||||
).getTime();
|
||||
? props.time
|
||||
: (props.time instanceof Date
|
||||
? props.time
|
||||
: new Date(props.time)
|
||||
).getTime();
|
||||
const invalid = Number.isNaN(_time);
|
||||
const absolute = !invalid ? dateTimeFormat.format(_time) : i18n.ts._ago.invalid;
|
||||
|
||||
|
@ -46,20 +46,30 @@ const relative = computed<string>(() => {
|
|||
return ago >= 31536000
|
||||
? i18n.t("_ago.yearsAgo", { n: Math.floor(ago / 31536000).toString() })
|
||||
: ago >= 2592000
|
||||
? i18n.t("_ago.monthsAgo", { n: Math.floor(ago / 2592000).toString() })
|
||||
: ago >= 604800
|
||||
? i18n.t("_ago.weeksAgo", { n: Math.floor(ago / 604800).toString() })
|
||||
: ago >= 86400
|
||||
? i18n.t("_ago.daysAgo", { n: Math.floor(ago / 86400).toString() })
|
||||
: ago >= 3600
|
||||
? i18n.t("_ago.hoursAgo", { n: Math.floor(ago / 3600).toString() })
|
||||
: ago >= 60
|
||||
? i18n.t("_ago.minutesAgo", { n: (~~(ago / 60)).toString() })
|
||||
: ago >= 10
|
||||
? i18n.t("_ago.secondsAgo", { n: (~~(ago % 60)).toString() })
|
||||
: ago >= -1
|
||||
? i18n.ts._ago.justNow
|
||||
: i18n.ts._ago.future;
|
||||
? i18n.t("_ago.monthsAgo", {
|
||||
n: Math.floor(ago / 2592000).toString(),
|
||||
})
|
||||
: ago >= 604800
|
||||
? i18n.t("_ago.weeksAgo", {
|
||||
n: Math.floor(ago / 604800).toString(),
|
||||
})
|
||||
: ago >= 86400
|
||||
? i18n.t("_ago.daysAgo", {
|
||||
n: Math.floor(ago / 86400).toString(),
|
||||
})
|
||||
: ago >= 3600
|
||||
? i18n.t("_ago.hoursAgo", {
|
||||
n: Math.floor(ago / 3600).toString(),
|
||||
})
|
||||
: ago >= 60
|
||||
? i18n.t("_ago.minutesAgo", { n: (~~(ago / 60)).toString() })
|
||||
: ago >= 10
|
||||
? i18n.t("_ago.secondsAgo", {
|
||||
n: (~~(ago % 60)).toString(),
|
||||
})
|
||||
: ago >= -1
|
||||
? i18n.ts._ago.justNow
|
||||
: i18n.ts._ago.future;
|
||||
});
|
||||
|
||||
let tickId: number;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { Ref } from "vue";
|
||||
import Ripple from "@/components/MkRipple.vue";
|
||||
import { popup } from "@/os";
|
||||
import type { Ref } from "vue";
|
||||
|
||||
export default {
|
||||
mounted(el: HTMLElement, binding: Ref<boolean>) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { entities } from "firefish-js";
|
||||
import type { entities } from "firefish-js";
|
||||
|
||||
export const notePage = (note: entities.Note) => {
|
||||
return `/notes/${note.id}`;
|
||||
|
|
|
@ -7,11 +7,11 @@ import "vite/modulepreload-polyfill";
|
|||
|
||||
import "@/style.scss";
|
||||
|
||||
import "@phosphor-icons/web/fill";
|
||||
import "@phosphor-icons/web/bold";
|
||||
import "@phosphor-icons/web/regular";
|
||||
import "@phosphor-icons/web/light";
|
||||
import "@phosphor-icons/web/duotone";
|
||||
import "@phosphor-icons/web/fill";
|
||||
import "@phosphor-icons/web/light";
|
||||
import "@phosphor-icons/web/regular";
|
||||
|
||||
// #region account indexedDB migration
|
||||
|
||||
|
@ -22,6 +22,7 @@ if (accounts) {
|
|||
}
|
||||
// #endregion
|
||||
|
||||
import { compareVersions } from "compare-versions";
|
||||
import {
|
||||
computed,
|
||||
createApp,
|
||||
|
@ -30,31 +31,30 @@ import {
|
|||
version as vueVersion,
|
||||
watch,
|
||||
} from "vue";
|
||||
import { compareVersions } from "compare-versions";
|
||||
import { set } from "@/scripts/idb-proxy";
|
||||
|
||||
import widgets from "@/widgets";
|
||||
import directives from "@/directives";
|
||||
import { login, refreshAccount, signout, updateAccount } from "@/account";
|
||||
import components from "@/components";
|
||||
import { lang, ui, version } from "@/config";
|
||||
import { applyTheme } from "@/scripts/theme";
|
||||
import { isDeviceDarkmode } from "@/scripts/is-device-darkmode";
|
||||
import directives from "@/directives";
|
||||
import { i18n } from "@/i18n";
|
||||
import { alert, api, confirm, popup, post, toast } from "@/os";
|
||||
import { stream } from "@/stream";
|
||||
import * as sound from "@/scripts/sound";
|
||||
import { login, refreshAccount, signout, updateAccount } from "@/account";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import { ColdDeviceStorage, defaultStore } from "@/store";
|
||||
import { fetchInstance, instance } from "@/instance";
|
||||
import { makeHotkey } from "@/scripts/hotkey";
|
||||
import { search } from "@/scripts/search";
|
||||
import { alert, api, confirm, popup, post, toast } from "@/os";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import { deviceKind } from "@/scripts/device-kind";
|
||||
import { initializeSw } from "@/scripts/initialize-sw";
|
||||
import { reloadChannel } from "@/scripts/unison-reload";
|
||||
import { reactionPicker } from "@/scripts/reaction-picker";
|
||||
import { getUrlWithoutLoginId } from "@/scripts/login-id";
|
||||
import { getAccountFromId } from "@/scripts/get-account-from-id";
|
||||
import { makeHotkey } from "@/scripts/hotkey";
|
||||
import { initializeSw } from "@/scripts/initialize-sw";
|
||||
import { isDeviceDarkmode } from "@/scripts/is-device-darkmode";
|
||||
import { getUrlWithoutLoginId } from "@/scripts/login-id";
|
||||
import { reactionPicker } from "@/scripts/reaction-picker";
|
||||
import { search } from "@/scripts/search";
|
||||
import * as sound from "@/scripts/sound";
|
||||
import { applyTheme } from "@/scripts/theme";
|
||||
import { reloadChannel } from "@/scripts/unison-reload";
|
||||
import { ColdDeviceStorage, defaultStore } from "@/store";
|
||||
import { stream } from "@/stream";
|
||||
import widgets from "@/widgets";
|
||||
|
||||
function checkForSplash() {
|
||||
const splash = document.getElementById("splash");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { computed, reactive } from "vue";
|
||||
import type * as firefish from "firefish-js";
|
||||
import { computed, reactive } from "vue";
|
||||
import { api } from "./os";
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { computed, reactive } from "vue";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import { search } from "@/scripts/search";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
import { ui } from "@/config";
|
||||
import { unisonReload } from "@/scripts/unison-reload";
|
||||
import { i18n } from "@/i18n";
|
||||
import * as os from "@/os";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import icon from "@/scripts/icon";
|
||||
import { search } from "@/scripts/search";
|
||||
import { unisonReload } from "@/scripts/unison-reload";
|
||||
|
||||
export const navbarItemDef = reactive({
|
||||
notifications: {
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
import { EventEmitter } from "eventemitter3";
|
||||
import type { Component, ShallowRef } from "vue";
|
||||
import { shallowRef } from "vue";
|
||||
import { pleaseLogin } from "@/scripts/please-login";
|
||||
import { safeURIDecode } from "@/scripts/safe-uri-decode";
|
||||
import { pleaseLogin } from "@/scripts/please-login";
|
||||
|
||||
interface RouteDef {
|
||||
path: string;
|
||||
|
@ -112,7 +112,7 @@ export class Router extends EventEmitter<{
|
|||
let parts = [..._parts];
|
||||
const props = new Map<string, string>();
|
||||
|
||||
pathMatchLoop: for (const p of parsePath(route.path)) {
|
||||
for (const p of parsePath(route.path)) {
|
||||
if (typeof p === "string") {
|
||||
if (p === parts[0]) {
|
||||
parts.shift();
|
||||
|
@ -128,7 +128,7 @@ export class Router extends EventEmitter<{
|
|||
props.set(p.name, safeURIDecode(parts.join("/")));
|
||||
parts = [];
|
||||
}
|
||||
break pathMatchLoop;
|
||||
break;
|
||||
} else {
|
||||
if (p.startsWith) {
|
||||
if (parts[0] == null || !parts[0].startsWith(p.startsWith))
|
||||
|
@ -159,7 +159,7 @@ export class Router extends EventEmitter<{
|
|||
child,
|
||||
};
|
||||
} else {
|
||||
continue forEachRouteLoop;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// TODO: なんでもかんでもos.tsに突っ込むのやめたいのでよしなに分割する
|
||||
|
||||
import { EventEmitter } from "eventemitter3";
|
||||
import * as firefish from "firefish-js";
|
||||
import insertTextAtCursor from "insert-text-at-cursor";
|
||||
import type { Component, Ref } from "vue";
|
||||
import { defineAsyncComponent, markRaw, ref } from "vue";
|
||||
import { EventEmitter } from "eventemitter3";
|
||||
import insertTextAtCursor from "insert-text-at-cursor";
|
||||
import * as firefish from "firefish-js";
|
||||
import { i18n } from "./i18n";
|
||||
import { apiUrl, url } from "@/config";
|
||||
import MkPostFormDialog from "@/components/MkPostFormDialog.vue";
|
||||
import MkWaitingDialog from "@/components/MkWaitingDialog.vue";
|
||||
import MkToast from "@/components/MkToast.vue";
|
||||
import MkDialog from "@/components/MkDialog.vue";
|
||||
import type { MenuItem } from "@/types/menu";
|
||||
import MkPostFormDialog from "@/components/MkPostFormDialog.vue";
|
||||
import MkToast from "@/components/MkToast.vue";
|
||||
import MkWaitingDialog from "@/components/MkWaitingDialog.vue";
|
||||
import { apiUrl, url } from "@/config";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import type { MenuItem } from "@/types/menu";
|
||||
|
||||
export const pendingApiRequestsCount = ref(0);
|
||||
|
||||
|
|
|
@ -127,18 +127,18 @@ const pagination = {
|
|||
...(state.value === "federating"
|
||||
? { federating: true }
|
||||
: state.value === "subscribing"
|
||||
? { subscribing: true }
|
||||
: state.value === "publishing"
|
||||
? { publishing: true }
|
||||
: state.value === "suspended"
|
||||
? { suspended: true }
|
||||
: state.value === "blocked"
|
||||
? { blocked: true }
|
||||
: state.value === "silenced"
|
||||
? { silenced: true }
|
||||
: state.value === "notResponding"
|
||||
? { notResponding: true }
|
||||
: {}),
|
||||
? { subscribing: true }
|
||||
: state.value === "publishing"
|
||||
? { publishing: true }
|
||||
: state.value === "suspended"
|
||||
? { suspended: true }
|
||||
: state.value === "blocked"
|
||||
? { blocked: true }
|
||||
: state.value === "silenced"
|
||||
? { silenced: true }
|
||||
: state.value === "notResponding"
|
||||
? { notResponding: true }
|
||||
: {}),
|
||||
})),
|
||||
};
|
||||
|
||||
|
|
|
@ -105,8 +105,8 @@ async function init() {
|
|||
provider.value = meta.enableHcaptcha
|
||||
? "hcaptcha"
|
||||
: meta.enableRecaptcha
|
||||
? "recaptcha"
|
||||
: null;
|
||||
? "recaptcha"
|
||||
: null;
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
|
|
@ -51,23 +51,23 @@ const label =
|
|||
props.type === "process"
|
||||
? "Process"
|
||||
: props.type === "active"
|
||||
? "Active"
|
||||
: props.type === "delayed"
|
||||
? "Delayed"
|
||||
: props.type === "waiting"
|
||||
? "Waiting"
|
||||
: ("?" as never);
|
||||
? "Active"
|
||||
: props.type === "delayed"
|
||||
? "Delayed"
|
||||
: props.type === "waiting"
|
||||
? "Waiting"
|
||||
: ("?" as never);
|
||||
|
||||
const color =
|
||||
props.type === "process"
|
||||
? "#c4a7e7"
|
||||
: props.type === "active"
|
||||
? "#31748f"
|
||||
: props.type === "delayed"
|
||||
? "#eb6f92"
|
||||
: props.type === "waiting"
|
||||
? "#f6c177"
|
||||
: ("?" as never);
|
||||
? "#31748f"
|
||||
: props.type === "delayed"
|
||||
? "#eb6f92"
|
||||
: props.type === "waiting"
|
||||
? "#f6c177"
|
||||
: ("?" as never);
|
||||
|
||||
onMounted(() => {
|
||||
const vLineColor = defaultStore.state.darkMode
|
||||
|
|
|
@ -96,23 +96,23 @@ const label =
|
|||
props.type === "process"
|
||||
? "Process"
|
||||
: props.type === "active"
|
||||
? "Active"
|
||||
: props.type === "delayed"
|
||||
? "Delayed"
|
||||
: props.type === "waiting"
|
||||
? "Waiting"
|
||||
: ("?" as never);
|
||||
? "Active"
|
||||
: props.type === "delayed"
|
||||
? "Delayed"
|
||||
: props.type === "waiting"
|
||||
? "Waiting"
|
||||
: ("?" as never);
|
||||
|
||||
const color =
|
||||
props.type === "process"
|
||||
? "#9ccfd8"
|
||||
: props.type === "active"
|
||||
? "#31748f"
|
||||
: props.type === "delayed"
|
||||
? "#eb6f92"
|
||||
: props.type === "waiting"
|
||||
? "#f6c177"
|
||||
: ("?" as never);
|
||||
? "#31748f"
|
||||
: props.type === "delayed"
|
||||
? "#eb6f92"
|
||||
: props.type === "waiting"
|
||||
? "#f6c177"
|
||||
: ("?" as never);
|
||||
|
||||
onMounted(() => {
|
||||
chartInstance = new Chart(chartEl.value, {
|
||||
|
|
|
@ -117,8 +117,8 @@ onMounted(() => {
|
|||
props.domain === "inbox"
|
||||
? "admin/queue/inbox-delayed"
|
||||
: props.domain === "deliver"
|
||||
? "admin/queue/deliver-delayed"
|
||||
: null,
|
||||
? "admin/queue/deliver-delayed"
|
||||
: null,
|
||||
{},
|
||||
).then((result) => {
|
||||
jobs.value = result;
|
||||
|
|
|
@ -290,14 +290,14 @@ async function init() {
|
|||
meta.sensitiveMediaDetectionSensitivity === "veryLow"
|
||||
? 0
|
||||
: meta.sensitiveMediaDetectionSensitivity === "low"
|
||||
? 1
|
||||
: meta.sensitiveMediaDetectionSensitivity === "medium"
|
||||
? 2
|
||||
: meta.sensitiveMediaDetectionSensitivity === "high"
|
||||
? 3
|
||||
: meta.sensitiveMediaDetectionSensitivity === "veryHigh"
|
||||
? 4
|
||||
: 0;
|
||||
? 1
|
||||
: meta.sensitiveMediaDetectionSensitivity === "medium"
|
||||
? 2
|
||||
: meta.sensitiveMediaDetectionSensitivity === "high"
|
||||
? 3
|
||||
: meta.sensitiveMediaDetectionSensitivity === "veryHigh"
|
||||
? 4
|
||||
: 0;
|
||||
setSensitiveFlagAutomatically.value = meta.setSensitiveFlagAutomatically;
|
||||
enableSensitiveMediaDetectionForVideos.value =
|
||||
meta.enableSensitiveMediaDetectionForVideos;
|
||||
|
@ -317,14 +317,14 @@ function save() {
|
|||
sensitiveMediaDetectionSensitivity.value === 0
|
||||
? "veryLow"
|
||||
: sensitiveMediaDetectionSensitivity.value === 1
|
||||
? "low"
|
||||
: sensitiveMediaDetectionSensitivity.value === 2
|
||||
? "medium"
|
||||
: sensitiveMediaDetectionSensitivity.value === 3
|
||||
? "high"
|
||||
: sensitiveMediaDetectionSensitivity.value === 4
|
||||
? "veryHigh"
|
||||
: 0,
|
||||
? "low"
|
||||
: sensitiveMediaDetectionSensitivity.value === 2
|
||||
? "medium"
|
||||
: sensitiveMediaDetectionSensitivity.value === 3
|
||||
? "high"
|
||||
: sensitiveMediaDetectionSensitivity.value === 4
|
||||
? "veryHigh"
|
||||
: 0,
|
||||
setSensitiveFlagAutomatically: setSensitiveFlagAutomatically.value,
|
||||
enableSensitiveMediaDetectionForVideos:
|
||||
enableSensitiveMediaDetectionForVideos.value,
|
||||
|
|
|
@ -98,14 +98,14 @@ function onEndpointChange() {
|
|||
p.type === "String"
|
||||
? ""
|
||||
: p.type === "Number"
|
||||
? 0
|
||||
: p.type === "Boolean"
|
||||
? false
|
||||
: p.type === "Array"
|
||||
? []
|
||||
: p.type === "Object"
|
||||
? {}
|
||||
: null;
|
||||
? 0
|
||||
: p.type === "Boolean"
|
||||
? false
|
||||
: p.type === "Array"
|
||||
? []
|
||||
: p.type === "Object"
|
||||
? {}
|
||||
: null;
|
||||
}
|
||||
body.value = JSON5.stringify(endpointBody, null, 2);
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/></template>
|
||||
<MkSpacer :content-max="800">
|
||||
<div class="attachments-timeline">
|
||||
<XTimeline ref="tl" class="tl" src="file" :fileId="fileId" />
|
||||
<XTimeline ref="tl" class="tl" src="file" :file-id="fileId" />
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
import { defineAsyncComponent, nextTick, ref } from "vue";
|
||||
import { Interpreter, Parser, utils } from "@syuilo/aiscript";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { compareVersions } from "compare-versions";
|
||||
import FormTextarea from "@/components/form/textarea.vue";
|
||||
import FormButton from "@/components/MkButton.vue";
|
||||
import FormInfo from "@/components/MkInfo.vue";
|
||||
|
@ -29,7 +30,6 @@ import { ColdDeviceStorage } from "@/store";
|
|||
import { unisonReload } from "@/scripts/unison-reload";
|
||||
import { i18n } from "@/i18n";
|
||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
||||
import { compareVersions } from "compare-versions";
|
||||
import icon from "@/scripts/icon";
|
||||
|
||||
const code = ref<string>();
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
color: color.forPreview
|
||||
? color.forPreview
|
||||
: theme.base === 'light'
|
||||
? '#5f5f5f'
|
||||
: '#dadada',
|
||||
? '#5f5f5f'
|
||||
: '#dadada',
|
||||
}"
|
||||
>
|
||||
A
|
||||
|
|
|
@ -270,12 +270,12 @@ definePageMetadata(
|
|||
src.value === "local"
|
||||
? "ph-users ph-lg"
|
||||
: src.value === "social"
|
||||
? "ph-handshake ph-lg"
|
||||
: src.value === "recommended"
|
||||
? "ph-thumbs-up ph-lg"
|
||||
: src.value === "global"
|
||||
? "ph-planet ph-lg"
|
||||
: "ph-house ph-lg",
|
||||
? "ph-handshake ph-lg"
|
||||
: src.value === "recommended"
|
||||
? "ph-thumbs-up ph-lg"
|
||||
: src.value === "global"
|
||||
? "ph-planet ph-lg"
|
||||
: "ph-house ph-lg",
|
||||
})),
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Interpreter, Parser, utils, values } from "@syuilo/aiscript";
|
||||
import { createAiScriptEnv } from "@/scripts/aiscript/api";
|
||||
import { inputText } from "@/os";
|
||||
import { createAiScriptEnv } from "@/scripts/aiscript/api";
|
||||
import {
|
||||
noteActions,
|
||||
notePostInterruptors,
|
||||
|
@ -114,7 +114,10 @@ function createPluginEnv(opts) {
|
|||
});
|
||||
}),
|
||||
"Plugin:register_page_view_interruptor": values.FN_NATIVE(([handler]) => {
|
||||
registerPageViewInterruptor({ pluginId: opts.plugin.id, handler });
|
||||
registerPageViewInterruptor({
|
||||
pluginId: opts.plugin.id,
|
||||
handler,
|
||||
});
|
||||
}),
|
||||
"Plugin:open_url": values.FN_NATIVE(([url]) => {
|
||||
window.open(url.value, "_blank");
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import type { AsyncComponentLoader } from "vue";
|
||||
import { defineAsyncComponent, inject } from "vue";
|
||||
import { Router } from "@/nirax";
|
||||
import { iAmModerator } from "@/account";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import MkLoading from "@/pages/_loading_.vue";
|
||||
import { Router } from "@/nirax";
|
||||
import MkError from "@/pages/_error_.vue";
|
||||
import MkLoading from "@/pages/_loading_.vue";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
// import { api } from "@/os";
|
||||
|
||||
// function getGuestTimelineStatus() {
|
||||
|
|
|
@ -88,7 +88,11 @@ export class Autocomplete {
|
|||
const isHashtag = hashtagIndex !== -1;
|
||||
const isMfmTag = mfmTagIndex !== -1;
|
||||
const isEmoji =
|
||||
emojiIndex !== -1 && text.split(/:[a-z0-9_+\-]+:/).pop()!.includes(":");
|
||||
emojiIndex !== -1 &&
|
||||
text
|
||||
.split(/:[a-z0-9_+\-]+:/)
|
||||
.pop()!
|
||||
.includes(":");
|
||||
|
||||
let opened = false;
|
||||
|
||||
|
|
|
@ -385,11 +385,11 @@ interface Plugin {
|
|||
ast: any[];
|
||||
}
|
||||
|
||||
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 darkTheme from "@/themes/d-rosepine.json5";
|
||||
|
||||
export class ColdDeviceStorage {
|
||||
public static default = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as firefish from "firefish-js";
|
||||
import { markRaw } from "vue";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
import { url } from "@/config";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
|
||||
export const stream = markRaw(
|
||||
new firefish.Stream(
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import { Interpreter, Parser, utils } from "@syuilo/aiscript";
|
||||
import {
|
||||
useWidgetPropsManager,
|
||||
import { useWidgetPropsManager } from "./widget";
|
||||
import type {
|
||||
WidgetComponentEmits,
|
||||
WidgetComponentExpose,
|
||||
WidgetComponentProps,
|
||||
} from "./widget";
|
||||
import type { WidgetComponentExpose } from "./widget";
|
||||
import type { GetFormResultType } from "@/scripts/form";
|
||||
import * as os from "@/os";
|
||||
import MkContainer from "@/components/MkContainer.vue";
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import { Interpreter, Parser } from "@syuilo/aiscript";
|
||||
import { createAiScriptEnv } from "@/scripts/aiscript/api";
|
||||
import {
|
||||
useWidgetPropsManager,
|
||||
import { useWidgetPropsManager } from "./widget";
|
||||
import type {
|
||||
WidgetComponentEmits,
|
||||
WidgetComponentExpose,
|
||||
WidgetComponentProps,
|
||||
} from "./widget";
|
||||
import type { WidgetComponentExpose } from "./widget";
|
||||
import { createAiScriptEnv } from "@/scripts/aiscript/api";
|
||||
import type { GetFormResultType } from "@/scripts/form";
|
||||
import * as os from "@/os";
|
||||
import { $i } from "@/reactiveAccount";
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
widgetProps.src === "list"
|
||||
? widgetProps.list.name
|
||||
: widgetProps.src === "antenna"
|
||||
? widgetProps.antenna.name
|
||||
: i18n.t("_timelines." + widgetProps.src)
|
||||
? widgetProps.antenna.name
|
||||
: i18n.t("_timelines." + widgetProps.src)
|
||||
}}</span>
|
||||
<i
|
||||
:class="
|
||||
|
@ -57,8 +57,8 @@
|
|||
widgetProps.src === 'list'
|
||||
? `list:${widgetProps.list.id}`
|
||||
: widgetProps.src === 'antenna'
|
||||
? `antenna:${widgetProps.antenna.id}`
|
||||
: widgetProps.src
|
||||
? `antenna:${widgetProps.antenna.id}`
|
||||
: widgetProps.src
|
||||
"
|
||||
:src="widgetProps.src"
|
||||
:list="widgetProps.list ? widgetProps.list.id : null"
|
||||
|
|
|
@ -32,15 +32,9 @@
|
|||
"types": [
|
||||
"vite/client",
|
||||
],
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
],
|
||||
"lib": ["esnext", "dom"],
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"./**/*.vue"
|
||||
]
|
||||
"include": ["./**/*.ts", "./**/*.vue"]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue