fix: can't create channel

wip: disable federation
This commit is contained in:
아르페 2023-12-18 04:08:21 +09:00
parent aaebd83ca7
commit c3fdea6b62
No known key found for this signature in database
GPG key ID: B1EFBBF5C93FF78F
20 changed files with 179 additions and 24 deletions

1
locales/index.d.ts vendored
View file

@ -2480,6 +2480,7 @@ export interface Locale {
"specifiedDescription": string;
"disableFederation": string;
"disableFederationDescription": string;
"federationDisabledByAdmin": string;
};
"_postForm": {
"signinRequiredPlaceholder": string;

View file

@ -2381,6 +2381,7 @@ _visibility:
specifiedDescription: "指定したユーザーのみに公開"
disableFederation: "連合なし"
disableFederationDescription: "他サーバーへの配信を行いません"
federationDisabledByAdmin: "管理者によって連合がオフになった"
_postForm:
signinRequiredPlaceholder: "ノートを作成するにはログインが必要です。"

View file

@ -1,6 +1,6 @@
{
"name": "lycheebridge",
"version": "2023.12.3",
"version": "2023.12.4-beta.0",
"basedCherryPickVersion": "4.6.0-beta.4",
"basedMisskeyVersion": "2023.12.0-beta.4",
"codename": "nasubi",

View file

@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class applyDatabaseChanges1702711709526 {
name = 'applyDatabaseChanges1702711709526'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "poll_vote" DROP CONSTRAINT "FK_poll_vote_poll"`);
await queryRunner.query(`DROP INDEX "public"."IDX_2cd3b2a6b4cf0b910b260afe08"`);
await queryRunner.query(`DROP INDEX "public"."IDX_renote_muting_muteeId"`);
await queryRunner.query(`DROP INDEX "public"."IDX_renote_muting_muterId"`);
await queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "noteEditHistory" SET NOT NULL`);
await queryRunner.query(`COMMENT ON COLUMN "event"."metadata" IS 'metadata object describing the event. Follows https://schema.org/Event'`);
await queryRunner.query(`ALTER TABLE "event" ALTER COLUMN "metadata" SET DEFAULT '{"@context":"https://schema.org/","@type":"Event"}'`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://github.com/LycheeBridge/LycheeBridge'`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://github.com/LycheeBridge/LycheeBridge/issues/new'`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{ "admin", "administrator", "root", "system", "maintainer", "host", "mod", "moderator", "owner", "superuser", "staff", "auth", "i", "me", "everyone", "all", "mention", "mentions", "example", "user", "users", "account", "accounts", "official", "help", "helps", "support", "supports", "info", "information", "informations", "announce", "announces", "announcement", "announcements", "notice", "notification", "notifications", "dev", "developer", "developers", "tech", "misskey", "cherrypick" }'`);
await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b"`);
await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "UQ_da851e06d0dfe2ef397d8b1bf1b"`);
await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c"`);
await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "UQ_e263909ca4fe5d57f8d4230dd5c"`);
await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6"`);
await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "UQ_f4853eb41ab722fe05f81cedeb6"`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9"`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "UQ_51cb79b5555effaf7d69ba1cff9"`);
await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "FK_10c146e4b39b443ede016f6736d"`);
await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "UQ_10c146e4b39b443ede016f6736d"`);
await queryRunner.query(`ALTER TABLE "flash" ALTER COLUMN "visibility" SET NOT NULL`);
await queryRunner.query(`CREATE INDEX "IDX_3fcc2c589eaefc205e0714b99c" ON "ad" ("startsAt") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c71faf11f0a28a5c0bb506203c" ON "channel_favorite" ("userId", "channelId") `);
await queryRunner.query(`CREATE INDEX "IDX_f7b9d338207e40e768e4a5265a" ON "instance" ("firstRetrievedAt") `);
await queryRunner.query(`CREATE INDEX "IDX_7eac97594bcac5ffcf2068089b" ON "renote_muting" ("muteeId") `);
await queryRunner.query(`CREATE INDEX "IDX_7aa72a5fe76019bfe8e5e0e8b7" ON "renote_muting" ("muterId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0d801c609cec4e9eb4b6b4490c" ON "renote_muting" ("muterId", "muteeId") `);
await queryRunner.query(`CREATE INDEX "IDX_58699f75b9cf904f5f007909cb" ON "user_profile" ("birthday") `);
await queryRunner.query(`ALTER TABLE "renote_muting" ADD CONSTRAINT "FK_7eac97594bcac5ffcf2068089b6" FOREIGN KEY ("muteeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "renote_muting" ADD CONSTRAINT "FK_7aa72a5fe76019bfe8e5e0e8b7d" FOREIGN KEY ("muterId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "FK_10c146e4b39b443ede016f6736d" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "FK_10c146e4b39b443ede016f6736d"`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9"`);
await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6"`);
await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c"`);
await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b"`);
await queryRunner.query(`ALTER TABLE "renote_muting" DROP CONSTRAINT "FK_7aa72a5fe76019bfe8e5e0e8b7d"`);
await queryRunner.query(`ALTER TABLE "renote_muting" DROP CONSTRAINT "FK_7eac97594bcac5ffcf2068089b6"`);
await queryRunner.query(`DROP INDEX "public"."IDX_58699f75b9cf904f5f007909cb"`);
await queryRunner.query(`DROP INDEX "public"."IDX_0d801c609cec4e9eb4b6b4490c"`);
await queryRunner.query(`DROP INDEX "public"."IDX_7aa72a5fe76019bfe8e5e0e8b7"`);
await queryRunner.query(`DROP INDEX "public"."IDX_7eac97594bcac5ffcf2068089b"`);
await queryRunner.query(`DROP INDEX "public"."IDX_f7b9d338207e40e768e4a5265a"`);
await queryRunner.query(`DROP INDEX "public"."IDX_c71faf11f0a28a5c0bb506203c"`);
await queryRunner.query(`DROP INDEX "public"."IDX_3fcc2c589eaefc205e0714b99c"`);
await queryRunner.query(`ALTER TABLE "flash" ALTER COLUMN "visibility" DROP NOT NULL`);
await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "UQ_10c146e4b39b443ede016f6736d" UNIQUE ("userId")`);
await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "FK_10c146e4b39b443ede016f6736d" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "UQ_51cb79b5555effaf7d69ba1cff9" UNIQUE ("userId")`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "UQ_f4853eb41ab722fe05f81cedeb6" UNIQUE ("userId")`);
await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "UQ_e263909ca4fe5d57f8d4230dd5c" UNIQUE ("noteId")`);
await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "UQ_da851e06d0dfe2ef397d8b1bf1b" UNIQUE ("noteId")`);
await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{admin,administrator,root,system,maintainer,host,mod,moderator,owner,superuser,staff,auth,i,me,everyone,all,mention,mentions,example,user,users,account,accounts,official,help,helps,support,supports,info,information,informations,announce,announces,announcement,announcements,notice,notification,notifications,dev,developer,developers,tech,misskey,cherrypick}'`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "feedbackUrl" SET DEFAULT 'https://github.com/kokonect-link/cherrypick/issues/new'`);
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET DEFAULT 'https://github.com/kokonect-link/cherrypick'`);
await queryRunner.query(`ALTER TABLE "event" ALTER COLUMN "metadata" SET DEFAULT '{}'`);
await queryRunner.query(`COMMENT ON COLUMN "event"."metadata" IS 'metadata mapping for event with more user configurable optional information'`);
await queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "noteEditHistory" DROP NOT NULL`);
await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `);
await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `);
await queryRunner.query(`CREATE INDEX "IDX_2cd3b2a6b4cf0b910b260afe08" ON "instance" ("firstRetrievedAt") `);
await queryRunner.query(`ALTER TABLE "poll_vote" ADD CONSTRAINT "FK_poll_vote_poll" FOREIGN KEY ("noteId") REFERENCES "poll"("noteId") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
}

View file

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class disableFederation1702711992942 {
name = 'disableFederation1702711992942'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "disableFederation" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "disableFederation"`);
}
}

View file

@ -274,7 +274,7 @@ export function loadConfig(): Config {
videoThumbnailGenerator: config.videoThumbnailGenerator ?
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
: null,
userAgent: `CherryPick/${version} (${config.url})`,
userAgent: `LycheeBridge/${version} (${config.url})`,
clientEntry: clientManifest['src/_boot_.ts'],
clientManifestExists: clientManifestExists,
perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000,

View file

@ -678,4 +678,9 @@ export class MiMeta {
default: false,
})
public privateInstance: boolean;
@Column('boolean', {
default: false,
})
public disableFederation: boolean;
}

View file

@ -26,6 +26,7 @@ import type { MiNote } from '@/models/Note.js';
import { QueryService } from '@/core/QueryService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js';
import { IActivity } from '@/core/activitypub/type.js';
import { isPureRenote } from '@/misc/is-pure-renote.js';
@ -71,6 +72,7 @@ export class ActivityPubServerService {
private queueService: QueueService,
private userKeypairService: UserKeypairService,
private queryService: QueryService,
private metaService: MetaService,
) {
//this.createServer = this.createServer.bind(this);
}

View file

@ -483,6 +483,14 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
privateInstance: {
type: 'boolean',
optional: false, nullable: false,
},
disableFederation: {
type: 'boolean',
optional: false, nullable: false,
},
},
},
} as const;
@ -630,6 +638,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
skipCherryPickVersion: instance.skipCherryPickVersion,
disableTimelinePreview: instance.disableTimelinePreview,
privateInstance: instance.privateInstance,
disableFederation: instance.disableFederation,
};
});
}

View file

@ -164,6 +164,7 @@ export const paramDef = {
skipCherryPickVersion: { type: 'string', nullable: true },
disableTimelinePreview: { type: 'boolean' },
privateInstance: { type: 'boolean' },
disableFederation: { type: 'boolean' },
},
required: [],
} as const;
@ -661,6 +662,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.privateInstance = ps.privateInstance;
}
if (ps.disableFederation !== undefined) {
set.disableFederation = ps.disableFederation;
}
const before = await this.metaService.fetch(true);
await this.metaService.update(set);

View file

@ -52,7 +52,7 @@ export const meta = {
type: 'string',
optional: false, nullable: false,
format: 'url',
example: 'https://cherrypick.example.com',
example: 'https://example.lycheebridge',
},
description: {
type: 'string',
@ -223,6 +223,10 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
disableFederation: {
type: 'boolean',
optional: false, nullable: false,
},
features: {
type: 'object',
optional: true, nullable: false,
@ -390,6 +394,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
mediaProxy: this.config.mediaProxy,
disableTimelinePreview: instance.disableTimelinePreview,
privateInstance: instance.privateInstance,
disableFederation: instance.disableFederation,
...(ps.detail ? {
cacheRemoteFiles: instance.cacheRemoteFiles,

View file

@ -14,6 +14,7 @@ import type { MiChannel } from '@/models/Channel.js';
import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { MetaService } from '@/core/MetaService.js';
import { NoteCreateService } from '@/core/NoteCreateService.js';
import { DI } from '@/di-symbols.js';
import { isPureRenote } from '@/misc/is-pure-renote.js';
@ -212,13 +213,23 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private noteEntityService: NoteEntityService,
private noteCreateService: NoteCreateService,
private metaService: MetaService,
) {
super(meta, paramDef, async (ps, me) => {
const instance = await this.metaService.fetch(true);
let visibleUsers: MiUser[] = [];
if (ps.visibleUserIds) {
visibleUsers = await this.usersRepository.findBy({
id: In(ps.visibleUserIds),
});
if (instance.disableFederation) {
for (const user of visibleUsers) {
if (user.host !== null) {
const idx = visibleUsers.indexOf(user);
visibleUsers.splice(idx);
}
}
}
}
let files: MiDriveFile[] = [];
@ -349,7 +360,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
metadata: ps.event.metadata ?? {},
} : undefined,
cw: ps.cw,
localOnly: ps.localOnly,
localOnly: instance.disableFederation ? true : ps.localOnly,
reactionAcceptance: ps.reactionAcceptance,
disableRightClick: ps.disableRightClick,
visibility: ps.visibility,

View file

@ -1,7 +1,7 @@
/*
* version: 4.6.5
* basedMisskeyVersion: 2023.12.0-beta.3
* generatedAt: 2023-12-15T00:42:53.847Z
* version: 2023.12.3
* basedMisskeyVersion: 2023.12.0-beta.4
* generatedAt: 2023-12-17T19:06:53.890Z
*/
import type { SwitchCaseResponseType } from '../api.js';

View file

@ -1,7 +1,7 @@
/*
* version: 4.6.5
* basedMisskeyVersion: 2023.12.0-beta.3
* generatedAt: 2023-12-15T00:42:53.845Z
* version: 2023.12.3
* basedMisskeyVersion: 2023.12.0-beta.4
* generatedAt: 2023-12-17T19:06:53.888Z
*/
import type {

View file

@ -1,7 +1,7 @@
/*
* version: 4.6.5
* basedMisskeyVersion: 2023.12.0-beta.3
* generatedAt: 2023-12-15T00:42:53.843Z
* version: 2023.12.3
* basedMisskeyVersion: 2023.12.0-beta.4
* generatedAt: 2023-12-17T19:06:53.886Z
*/
import { operations } from './types.js';

View file

@ -1,7 +1,7 @@
/*
* version: 4.6.5
* basedMisskeyVersion: 2023.12.0-beta.3
* generatedAt: 2023-12-15T00:42:53.841Z
* version: 2023.12.3
* basedMisskeyVersion: 2023.12.0-beta.4
* generatedAt: 2023-12-17T19:06:53.885Z
*/
import { components } from './types.js';

View file

@ -2,9 +2,9 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
/*
* version: 4.6.5
* basedMisskeyVersion: 2023.12.0-beta.3
* generatedAt: 2023-12-15T00:42:53.760Z
* version: 2023.12.3
* basedMisskeyVersion: 2023.12.0-beta.4
* generatedAt: 2023-12-17T19:06:53.806Z
*/
/**
@ -4823,6 +4823,8 @@ export type operations = {
skipVersion: boolean;
skipCherryPickVersion?: string | null;
disableTimelinePreview: boolean;
privateInstance: boolean;
disableFederation: boolean;
};
};
};
@ -9007,6 +9009,7 @@ export type operations = {
skipCherryPickVersion?: string | null;
disableTimelinePreview?: boolean;
privateInstance?: boolean;
disableFederation?: boolean;
};
};
};
@ -19668,7 +19671,7 @@ export type operations = {
shortName: string | null;
/**
* Format: url
* @example https://cherrypick.example.com
* @example https://example.lycheebridge
*/
uri: string;
description: string | null;
@ -19717,6 +19720,7 @@ export type operations = {
mediaProxy: string;
disableTimelinePreview: boolean;
privateInstance: boolean;
disableFederation: boolean;
features?: {
registration: boolean;
localTimeline: boolean;

View file

@ -32,10 +32,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<span :class="$style.headerRightButtonText">{{ channel.name }}</span>
</button>
</template>
<button v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="channel != null || visibility === 'specified'" @click="toggleLocalOnly">
<button v-if="!instance.disableFederation" ref="localOnlyButton" v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="channel != null || visibility === 'specified'" @click="toggleLocalOnly">
<span v-if="!localOnly"><i class="ti ti-rocket"></i></span>
<span v-else><i class="ti ti-rocket-off"></i></span>
</button>
<button v-else v-tooltip="i18n.ts._visibility.federationDisabledByAdmin" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" disabled>
<span><i class="ti ti-rocket-off"></i></span>
</button>
<button v-click-anime v-tooltip="i18n.ts.reactionAcceptance" class="_button" :class="[$style.headerRightItem, { [$style.danger]: reactionAcceptance === 'likeOnly' }]" @click="toggleReactionAcceptance">
<span v-if="reactionAcceptance === 'likeOnly'"><i class="ti ti-heart"></i></span>
<span v-else-if="reactionAcceptance === 'likeOnlyForRemote'"><i class="ti ti-heart-plus"></i></span>
@ -175,6 +178,7 @@ const textareaEl = shallowRef<HTMLTextAreaElement | null>(null);
const cwInputEl = shallowRef<HTMLInputElement | null>(null);
const hashtagsInputEl = shallowRef<HTMLInputElement | null>(null);
const visibilityButton = shallowRef<HTMLElement | null>(null);
const localOnlyButton = shallowRef<HTMLElement | null>(null);
const posting = ref(false);
const posted = ref(false);
@ -335,6 +339,10 @@ if (props.channel) {
localOnly.value = true; // TODO:
}
if (instance.disableFederation) {
localOnly.value = true;
}
//
if (props.reply && ['home', 'followers', 'specified'].includes(props.reply.visibility)) {
if (props.reply.visibility === 'home' && visibility.value === 'followers') {
@ -573,6 +581,8 @@ function pushVisibleUser(user) {
function addVisibleUser() {
os.selectUser().then(user => {
if (user.host !== null) return;
pushVisibleUser(user);
if (!text.value.toLowerCase().includes(`@${user.username.toLowerCase()}`)) {

View file

@ -12,7 +12,7 @@
<html>
<head>
<meta charset="UTF-8" />
<title>misskey</title>
<title>LycheeBridge</title>
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
@ -23,7 +23,7 @@
img-src 'self' data: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;"
/>
<meta property="og:site_name" content="[DEV BUILD] Misskey" />
<meta property="og:site_name" content="[DEV BUILD] LycheeBridge" />
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>

View file

@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkStickyContainer>
<template #header>
<MkPageHeader v-model:tab="tab" :actions="$i ? headerActions : null" :tabs="$i ? headerTabs : headerTabsWhenNotLogin" :displayMyAvatar="true"/>
<MkPageHeader v-model:tab="tab" :actions="$i ? headerActions : undefined" :tabs="$i ? headerTabs : headerTabsWhenNotLogin"/>
</template>
<MkSpacer :contentMax="700">
<div v-if="tab === 'search'">
@ -63,6 +63,7 @@ import MkFoldableSection from '@/components/MkFoldableSection.vue';
import { $i } from '@/account.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { i18n } from '@/i18n.js';
import { useRouter } from '@/router.js';
const props = defineProps<{
query: string;
@ -74,6 +75,7 @@ const tab = ref('featured');
const searchQuery = ref('');
const searchType = ref('nameAndDescription');
const channelPagination = ref();
const router = useRouter();
onMounted(() => {
searchQuery.value = props.query ?? '';