mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-25 19:37:34 -07:00
fix: 🚸 make "show replies in timeline" work as expected
Co-authored-by: Syuilo <syuilotan@yahoo.co.jp>
This commit is contained in:
parent
47c077a7f3
commit
7f3b9b171c
24 changed files with 145 additions and 86 deletions
|
@ -0,0 +1,15 @@
|
|||
export class RemoveShowTimelineReplies1684206886988 {
|
||||
name = "RemoveShowTimelineReplies1684206886988";
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`,
|
||||
);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "user" ADD "showTimelineReplies" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -63,8 +63,6 @@ pub struct Model {
|
|||
pub hide_online_status: bool,
|
||||
#[sea_orm(column_name = "isDeleted")]
|
||||
pub is_deleted: bool,
|
||||
#[sea_orm(column_name = "showTimelineReplies")]
|
||||
pub show_timeline_replies: bool,
|
||||
#[sea_orm(column_name = "driveCapacityOverrideMb")]
|
||||
pub drive_capacity_override_mb: Option<i32>,
|
||||
#[sea_orm(column_name = "movedToUri")]
|
||||
|
|
|
@ -249,12 +249,6 @@ export class User {
|
|||
})
|
||||
public followersUri: string | null;
|
||||
|
||||
@Column("boolean", {
|
||||
default: false,
|
||||
comment: "Whether to show users replying to other users in the timeline.",
|
||||
})
|
||||
public showTimelineReplies: boolean;
|
||||
|
||||
@Index({ unique: true })
|
||||
@Column("char", {
|
||||
length: 16,
|
||||
|
|
|
@ -567,7 +567,6 @@ export const UserRepository = db.getRepository(User).extend({
|
|||
mutedInstances: profile!.mutedInstances,
|
||||
mutingNotificationTypes: profile!.mutingNotificationTypes,
|
||||
emailNotificationTypes: profile!.emailNotificationTypes,
|
||||
showTimelineReplies: user.showTimelineReplies || falsy,
|
||||
}
|
||||
: {}),
|
||||
|
||||
|
|
|
@ -279,7 +279,6 @@ export async function createPerson(
|
|||
tags,
|
||||
isBot,
|
||||
isCat: (person as any).isCat === true,
|
||||
showTimelineReplies: false,
|
||||
}),
|
||||
)) as IRemoteUser;
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ import { Brackets } from "typeorm";
|
|||
|
||||
export function generateRepliesQuery(
|
||||
q: SelectQueryBuilder<any>,
|
||||
me?: Pick<User, "id" | "showTimelineReplies"> | null,
|
||||
withReplies: boolean,
|
||||
me?: Pick<User, "id"> | null,
|
||||
) {
|
||||
if (me == null) {
|
||||
q.andWhere(
|
||||
|
@ -20,25 +21,21 @@ export function generateRepliesQuery(
|
|||
);
|
||||
}),
|
||||
);
|
||||
} else if (!me.showTimelineReplies) {
|
||||
} else if (!withReplies) {
|
||||
q.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where("note.replyId IS NULL") // 返信ではない
|
||||
.orWhere("note.replyUserId = :meId", { meId: me.id }) // 返信だけど自分のノートへの返信
|
||||
.orWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where(
|
||||
// 返信だけど自分の行った返信
|
||||
"note.replyId IS NOT NULL",
|
||||
).andWhere("note.userId = :meId", { meId: me.id });
|
||||
qb.where("note.replyId IS NOT NULL") // 返信だけど自分の行った返信
|
||||
.andWhere("note.userId = :meId", { meId: me.id });
|
||||
}),
|
||||
)
|
||||
.orWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where(
|
||||
// 返信だけど投稿者自身への返信
|
||||
"note.replyId IS NOT NULL",
|
||||
).andWhere("note.replyUserId = note.userId");
|
||||
qb.where("note.replyId IS NOT NULL") // 返信だけど投稿者自身への返信
|
||||
.andWhere("note.replyUserId = note.userId");
|
||||
}),
|
||||
);
|
||||
}),
|
||||
|
|
|
@ -106,7 +106,6 @@ export const paramDef = {
|
|||
isBot: { type: "boolean" },
|
||||
isCat: { type: "boolean" },
|
||||
speakAsCat: { type: "boolean" },
|
||||
showTimelineReplies: { type: "boolean" },
|
||||
injectFeaturedNote: { type: "boolean" },
|
||||
receiveAnnouncementEmail: { type: "boolean" },
|
||||
alwaysMarkNsfw: { type: "boolean" },
|
||||
|
@ -185,8 +184,6 @@ export default define(meta, paramDef, async (ps, _user, token) => {
|
|||
if (typeof ps.publicReactions === "boolean")
|
||||
profileUpdates.publicReactions = ps.publicReactions;
|
||||
if (typeof ps.isBot === "boolean") updates.isBot = ps.isBot;
|
||||
if (typeof ps.showTimelineReplies === "boolean")
|
||||
updates.showTimelineReplies = ps.showTimelineReplies;
|
||||
if (typeof ps.carefulBot === "boolean")
|
||||
profileUpdates.carefulBot = ps.carefulBot;
|
||||
if (typeof ps.autoAcceptFollowed === "boolean")
|
||||
|
|
|
@ -53,6 +53,11 @@ export const paramDef = {
|
|||
untilId: { type: "string", format: "misskey:id" },
|
||||
sinceDate: { type: "integer" },
|
||||
untilDate: { type: "integer" },
|
||||
withReplies: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Show replies in the timeline",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
@ -87,7 +92,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
||||
|
||||
generateRepliesQuery(query, user);
|
||||
generateRepliesQuery(query, ps.withReplies, user);
|
||||
if (user) {
|
||||
generateMutedUserQuery(query, user);
|
||||
generateMutedNoteQuery(query, user);
|
||||
|
|
|
@ -60,6 +60,11 @@ export const paramDef = {
|
|||
default: false,
|
||||
description: "Only show notes that have attached files.",
|
||||
},
|
||||
withReplies: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Show replies in the timeline",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
@ -104,7 +109,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.setParameters(followingQuery.getParameters());
|
||||
|
||||
generateChannelQuery(query, user);
|
||||
generateRepliesQuery(query, user);
|
||||
generateRepliesQuery(query, ps.withReplies, user);
|
||||
generateVisibilityQuery(query, user);
|
||||
generateMutedUserQuery(query, user);
|
||||
generateMutedNoteQuery(query, user);
|
||||
|
|
|
@ -63,6 +63,11 @@ export const paramDef = {
|
|||
untilId: { type: "string", format: "misskey:id" },
|
||||
sinceDate: { type: "integer" },
|
||||
untilDate: { type: "integer" },
|
||||
withReplies: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Show replies in the timeline",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
@ -97,7 +102,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
||||
|
||||
generateChannelQuery(query, user);
|
||||
generateRepliesQuery(query, user);
|
||||
generateRepliesQuery(query, ps.withReplies, user);
|
||||
generateVisibilityQuery(query, user);
|
||||
if (user) generateMutedUserQuery(query, user);
|
||||
if (user) generateMutedNoteQuery(query, user);
|
||||
|
|
|
@ -63,6 +63,11 @@ export const paramDef = {
|
|||
untilId: { type: "string", format: "misskey:id" },
|
||||
sinceDate: { type: "integer" },
|
||||
untilDate: { type: "integer" },
|
||||
withReplies: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Show replies in the timeline",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
@ -100,7 +105,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner");
|
||||
|
||||
generateChannelQuery(query, user);
|
||||
generateRepliesQuery(query, user);
|
||||
generateRepliesQuery(query, ps.withReplies, user);
|
||||
generateVisibilityQuery(query, user);
|
||||
if (user) generateMutedUserQuery(query, user);
|
||||
if (user) generateMutedNoteQuery(query, user);
|
||||
|
|
|
@ -54,6 +54,11 @@ export const paramDef = {
|
|||
default: false,
|
||||
description: "Only show notes that have attached files.",
|
||||
},
|
||||
withReplies: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Show replies in the timeline",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
@ -100,7 +105,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.setParameters(followingQuery.getParameters());
|
||||
|
||||
generateChannelQuery(query, user);
|
||||
generateRepliesQuery(query, user);
|
||||
generateRepliesQuery(query, ps.withReplies, user);
|
||||
generateVisibilityQuery(query, user);
|
||||
generateMutedUserQuery(query, user);
|
||||
generateMutedNoteQuery(query, user);
|
||||
|
|
|
@ -9,6 +9,7 @@ export default class extends Channel {
|
|||
public readonly chName = "globalTimeline";
|
||||
public static shouldShare = true;
|
||||
public static requireCredential = false;
|
||||
private withReplies: boolean;
|
||||
|
||||
constructor(id: string, connection: Channel["connection"]) {
|
||||
super(id, connection);
|
||||
|
@ -22,6 +23,8 @@ export default class extends Channel {
|
|||
return;
|
||||
}
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on("notesStream", this.onNote);
|
||||
}
|
||||
|
@ -31,7 +34,7 @@ export default class extends Channel {
|
|||
if (note.channelId != null) return;
|
||||
|
||||
// 関係ない返信は除外
|
||||
if (note.reply && !this.user!.showTimelineReplies) {
|
||||
if (note.reply && !this.withReplies) {
|
||||
const reply = note.reply;
|
||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||
if (
|
||||
|
|
|
@ -8,6 +8,7 @@ export default class extends Channel {
|
|||
public readonly chName = "homeTimeline";
|
||||
public static shouldShare = true;
|
||||
public static requireCredential = true;
|
||||
private withReplies: boolean;
|
||||
|
||||
constructor(id: string, connection: Channel["connection"]) {
|
||||
super(id, connection);
|
||||
|
@ -15,6 +16,8 @@ export default class extends Channel {
|
|||
}
|
||||
|
||||
public async init(params: any) {
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on("notesStream", this.onNote);
|
||||
}
|
||||
|
@ -39,7 +42,7 @@ export default class extends Channel {
|
|||
return;
|
||||
|
||||
// 関係ない返信は除外
|
||||
if (note.reply && !this.user!.showTimelineReplies) {
|
||||
if (note.reply && !this.withReplies) {
|
||||
const reply = note.reply;
|
||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||
if (
|
||||
|
|
|
@ -9,6 +9,7 @@ export default class extends Channel {
|
|||
public readonly chName = "hybridTimeline";
|
||||
public static shouldShare = true;
|
||||
public static requireCredential = true;
|
||||
private withReplies: boolean;
|
||||
|
||||
constructor(id: string, connection: Channel["connection"]) {
|
||||
super(id, connection);
|
||||
|
@ -24,6 +25,8 @@ export default class extends Channel {
|
|||
)
|
||||
return;
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on("notesStream", this.onNote);
|
||||
}
|
||||
|
@ -56,7 +59,7 @@ export default class extends Channel {
|
|||
return;
|
||||
|
||||
// 関係ない返信は除外
|
||||
if (note.reply && !this.user!.showTimelineReplies) {
|
||||
if (note.reply && !this.withReplies) {
|
||||
const reply = note.reply;
|
||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||
if (
|
||||
|
|
|
@ -8,6 +8,7 @@ export default class extends Channel {
|
|||
public readonly chName = "localTimeline";
|
||||
public static shouldShare = true;
|
||||
public static requireCredential = false;
|
||||
private withReplies: boolean;
|
||||
|
||||
constructor(id: string, connection: Channel["connection"]) {
|
||||
super(id, connection);
|
||||
|
@ -21,6 +22,8 @@ export default class extends Channel {
|
|||
return;
|
||||
}
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on("notesStream", this.onNote);
|
||||
}
|
||||
|
@ -32,7 +35,7 @@ export default class extends Channel {
|
|||
return;
|
||||
|
||||
// 関係ない返信は除外
|
||||
if (note.reply && !this.user!.showTimelineReplies) {
|
||||
if (note.reply && !this.withReplies) {
|
||||
const reply = note.reply;
|
||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||
if (
|
||||
|
|
|
@ -9,6 +9,7 @@ export default class extends Channel {
|
|||
public readonly chName = "recommendedTimeline";
|
||||
public static shouldShare = true;
|
||||
public static requireCredential = true;
|
||||
private withReplies: boolean;
|
||||
|
||||
constructor(id: string, connection: Channel["connection"]) {
|
||||
super(id, connection);
|
||||
|
@ -24,6 +25,8 @@ export default class extends Channel {
|
|||
)
|
||||
return;
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on("notesStream", this.onNote);
|
||||
}
|
||||
|
@ -54,7 +57,7 @@ export default class extends Channel {
|
|||
return;
|
||||
|
||||
// 関係ない返信は除外
|
||||
if (note.reply && !this.user!.showTimelineReplies) {
|
||||
if (note.reply && !this.withReplies) {
|
||||
const reply = note.reply;
|
||||
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
|
||||
if (
|
||||
|
|
|
@ -44,12 +44,7 @@ describe("ユーザー", () => {
|
|||
};
|
||||
|
||||
type MeDetailed = UserDetailedNotMe &
|
||||
misskey.entities.MeDetailed & {
|
||||
showTimelineReplies: boolean;
|
||||
achievements: object[];
|
||||
loggedInDays: number;
|
||||
policies: object;
|
||||
};
|
||||
misskey.entities.MeDetailed
|
||||
|
||||
type User = MeDetailed & { token: string };
|
||||
|
||||
|
@ -172,9 +167,6 @@ describe("ユーザー", () => {
|
|||
mutedInstances: user.mutedInstances,
|
||||
mutingNotificationTypes: user.mutingNotificationTypes,
|
||||
emailNotificationTypes: user.emailNotificationTypes,
|
||||
showTimelineReplies: user.showTimelineReplies,
|
||||
achievements: user.achievements,
|
||||
loggedInDays: user.loggedInDays,
|
||||
policies: user.policies,
|
||||
...(security
|
||||
? {
|
||||
|
@ -479,13 +471,6 @@ describe("ユーザー", () => {
|
|||
"follow",
|
||||
"receiveFollowRequest",
|
||||
]);
|
||||
assert.strictEqual(response.showTimelineReplies, false);
|
||||
assert.deepStrictEqual(response.achievements, []);
|
||||
assert.deepStrictEqual(response.loggedInDays, 0);
|
||||
assert.deepStrictEqual(response.policies, DEFAULT_POLICIES);
|
||||
assert.notStrictEqual(response.email, undefined);
|
||||
assert.strictEqual(response.emailVerified, false);
|
||||
assert.deepStrictEqual(response.securityKeysList, []);
|
||||
});
|
||||
|
||||
//#endregion
|
||||
|
@ -551,8 +536,6 @@ describe("ユーザー", () => {
|
|||
{ parameters: (): object => ({ isBot: false }) },
|
||||
{ parameters: (): object => ({ isCat: true }) },
|
||||
{ parameters: (): object => ({ isCat: false }) },
|
||||
{ parameters: (): object => ({ showTimelineReplies: true }) },
|
||||
{ parameters: (): object => ({ showTimelineReplies: false }) },
|
||||
{ parameters: (): object => ({ injectFeaturedNote: true }) },
|
||||
{ parameters: (): object => ({ injectFeaturedNote: false }) },
|
||||
{ parameters: (): object => ({ receiveAnnouncementEmail: true }) },
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<template>
|
||||
<button v-if="!hideMenu" class="menu _button" @click.stop="menu" v-tooltip="i18n.ts.menu">
|
||||
<button
|
||||
v-if="!hideMenu"
|
||||
class="menu _button"
|
||||
@click.stop="menu"
|
||||
v-tooltip="i18n.ts.menu"
|
||||
>
|
||||
<i class="ph-dots-three-outline ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
|
|
|
@ -91,7 +91,12 @@ if (props.src === "antenna") {
|
|||
connection.on("note", prepend);
|
||||
} else if (props.src === "home") {
|
||||
endpoint = "notes/timeline";
|
||||
connection = stream.useChannel("homeTimeline");
|
||||
query = {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
};
|
||||
connection = stream.useChannel("homeTimeline", {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
});
|
||||
connection.on("note", prepend);
|
||||
|
||||
connection2 = stream.useChannel("main");
|
||||
|
@ -102,28 +107,48 @@ if (props.src === "antenna") {
|
|||
tlHintClosed = defaultStore.state.tlHomeHintClosed;
|
||||
} else if (props.src === "local") {
|
||||
endpoint = "notes/local-timeline";
|
||||
connection = stream.useChannel("localTimeline");
|
||||
query = {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
};
|
||||
connection = stream.useChannel("localTimeline", {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
});
|
||||
connection.on("note", prepend);
|
||||
|
||||
tlHint = i18n.ts._tutorial.step5_4;
|
||||
tlHintClosed = defaultStore.state.tlLocalHintClosed;
|
||||
} else if (props.src === "recommended") {
|
||||
endpoint = "notes/recommended-timeline";
|
||||
connection = stream.useChannel("recommendedTimeline");
|
||||
query = {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
};
|
||||
connection = stream.useChannel("recommendedTimeline", {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
});
|
||||
connection.on("note", prepend);
|
||||
|
||||
tlHint = i18n.ts._tutorial.step5_6;
|
||||
tlHintClosed = defaultStore.state.tlRecommendedHintClosed;
|
||||
} else if (props.src === "social") {
|
||||
endpoint = "notes/hybrid-timeline";
|
||||
connection = stream.useChannel("hybridTimeline");
|
||||
query = {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
};
|
||||
connection = stream.useChannel("hybridTimeline", {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
});
|
||||
connection.on("note", prepend);
|
||||
|
||||
tlHint = i18n.ts._tutorial.step5_5;
|
||||
tlHintClosed = defaultStore.state.tlSocialHintClosed;
|
||||
} else if (props.src === "global") {
|
||||
endpoint = "notes/global-timeline";
|
||||
connection = stream.useChannel("globalTimeline");
|
||||
query = {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
};
|
||||
connection = stream.useChannel("globalTimeline", {
|
||||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
});
|
||||
connection.on("note", prepend);
|
||||
|
||||
tlHint = i18n.ts._tutorial.step5_7;
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<FormSwitch v-model="disablePagesScript" class="_formBlock">{{
|
||||
i18n.ts.disablePagesScript
|
||||
}}</FormSwitch>
|
||||
<FormSwitch v-model="profile.showTimelineReplies" class="_formBlock"
|
||||
<FormSwitch v-model="showTimelineReplies" class="_formBlock"
|
||||
>{{ i18n.ts.flagShowTimelineReplies
|
||||
}}<template #caption
|
||||
>{{ i18n.ts.flagShowTimelineRepliesDescription }}
|
||||
|
@ -258,24 +258,6 @@ const lang = ref(localStorage.getItem("lang"));
|
|||
const fontSize = ref(localStorage.getItem("fontSize"));
|
||||
const useSystemFont = ref(localStorage.getItem("useSystemFont") != null);
|
||||
|
||||
const profile = reactive({
|
||||
showTimelineReplies: $i?.showTimelineReplies,
|
||||
});
|
||||
watch(
|
||||
() => profile,
|
||||
() => {
|
||||
save();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
function save() {
|
||||
os.apiWithDialog("i/update", {
|
||||
showTimelineReplies: !!profile.showTimelineReplies,
|
||||
});
|
||||
}
|
||||
|
||||
async function reloadAsk() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: "info",
|
||||
|
@ -360,6 +342,9 @@ const swipeOnDesktop = computed(
|
|||
const showAdminUpdates = computed(
|
||||
defaultStore.makeGetterSetter("showAdminUpdates")
|
||||
);
|
||||
const showTimelineReplies = computed(
|
||||
defaultStore.makeGetterSetter("showTimelineReplies")
|
||||
);
|
||||
|
||||
watch(lang, () => {
|
||||
localStorage.setItem("lang", lang.value as string);
|
||||
|
|
|
@ -115,6 +115,7 @@ const defaultStoreSaveKeys: (keyof (typeof defaultStore)["state"])[] = [
|
|||
"enableCustomKaTeXMacro",
|
||||
"enableEmojiReactions",
|
||||
"showEmojisInReactionNotifications",
|
||||
"showTimelineReplies",
|
||||
];
|
||||
const coldDeviceStorageSaveKeys: (keyof typeof ColdDeviceStorage.default)[] = [
|
||||
"lightTheme",
|
||||
|
|
|
@ -330,6 +330,10 @@ export const defaultStore = markRaw(
|
|||
where: "account",
|
||||
default: true,
|
||||
},
|
||||
showTimelineReplies: {
|
||||
where: "device",
|
||||
default: true,
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
@ -3,13 +3,30 @@ import { markRaw } from "vue";
|
|||
import { $i } from "@/account";
|
||||
import { url } from "@/config";
|
||||
|
||||
export const stream = markRaw(
|
||||
new Misskey.Stream(
|
||||
url,
|
||||
$i
|
||||
? {
|
||||
token: $i.token,
|
||||
}
|
||||
: null,
|
||||
),
|
||||
);
|
||||
let stream: Misskey.Stream | null = null;
|
||||
|
||||
export function useStream(): Misskey.Stream {
|
||||
if (stream) return stream;
|
||||
|
||||
stream = markRaw(
|
||||
new Misskey.Stream(
|
||||
url,
|
||||
$i
|
||||
? {
|
||||
token: $i.token,
|
||||
}
|
||||
: null
|
||||
)
|
||||
);
|
||||
|
||||
window.setTimeout(heartbeat, 1000 * 60);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
function heartbeat(): void {
|
||||
if (stream != null && document.visibilityState === "visible") {
|
||||
stream.send("ping");
|
||||
}
|
||||
window.setTimeout(heartbeat, 1000 * 60);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue