Art/add media timeline (#11)

This commit is contained in:
Ced 2023-08-12 00:11:13 +09:00 committed by GitHub
parent dff11f8aa9
commit ca1a9d1505
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 64 additions and 2 deletions

View file

@ -1482,6 +1482,8 @@ _aboutMisskey:
contributors: "Main contributors" contributors: "Main contributors"
allContributors: "All contributors" allContributors: "All contributors"
source: "Source code" source: "Source code"
originalSource: "Original source code"
ioSource: "Misskey.io's source code"
translation: "Translate Misskey" translation: "Translate Misskey"
donate: "Donate to Misskey" donate: "Donate to Misskey"
morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰" morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰"
@ -1847,6 +1849,7 @@ _instanceCharts:
_timelines: _timelines:
home: "Home" home: "Home"
local: "Local" local: "Local"
media: "Media"
social: "Social" social: "Social"
global: "Global" global: "Global"
_play: _play:

3
locales/index.d.ts vendored
View file

@ -1583,6 +1583,8 @@ export interface Locale {
"contributors": string; "contributors": string;
"allContributors": string; "allContributors": string;
"source": string; "source": string;
"originalSource": string;
"ioSource": string;
"translation": string; "translation": string;
"donate": string; "donate": string;
"morePatrons": string; "morePatrons": string;
@ -1978,6 +1980,7 @@ export interface Locale {
"_timelines": { "_timelines": {
"home": string; "home": string;
"local": string; "local": string;
"media": string;
"social": string; "social": string;
"global": string; "global": string;
}; };

View file

@ -1501,6 +1501,8 @@ _aboutMisskey:
contributors: "主なコントリビューター" contributors: "主なコントリビューター"
allContributors: "全てのコントリビューター" allContributors: "全てのコントリビューター"
source: "ソースコード" source: "ソースコード"
originalSource: "本家のソースコード"
ioSource: "Misskey.ioのソースコード"
translation: "Misskeyを翻訳" translation: "Misskeyを翻訳"
donate: "Misskeyに寄付" donate: "Misskeyに寄付"
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰" morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
@ -1894,6 +1896,7 @@ _instanceCharts:
_timelines: _timelines:
home: "ホーム" home: "ホーム"
local: "ローカル" local: "ローカル"
media: "メディア"
social: "ソーシャル" social: "ソーシャル"
global: "グローバル" global: "グローバル"

View file

@ -14,6 +14,7 @@ class GlobalTimelineChannel extends Channel {
public static shouldShare = true; public static shouldShare = true;
public static requireCredential = false; public static requireCredential = false;
private withReplies: boolean; private withReplies: boolean;
private withFiles: boolean;
constructor( constructor(
private metaService: MetaService, private metaService: MetaService,
@ -33,6 +34,7 @@ class GlobalTimelineChannel extends Channel {
if (!policies.gtlAvailable) return; if (!policies.gtlAvailable) return;
this.withReplies = params.withReplies as boolean; this.withReplies = params.withReplies as boolean;
this.withFiles = params.withFiles as boolean;
// Subscribe events // Subscribe events
this.subscriber.on('notesStream', this.onNote); this.subscriber.on('notesStream', this.onNote);
@ -43,6 +45,9 @@ class GlobalTimelineChannel extends Channel {
if (note.visibility !== 'public') return; if (note.visibility !== 'public') return;
if (note.channelId != null) return; if (note.channelId != null) return;
// ファイルを含まない投稿は除外
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
// リプライなら再pack // リプライなら再pack
if (note.replyId != null) { if (note.replyId != null) {
note.reply = await this.noteEntityService.pack(note.replyId, this.user, { note.reply = await this.noteEntityService.pack(note.replyId, this.user, {

View file

@ -12,6 +12,7 @@ class HomeTimelineChannel extends Channel {
public static shouldShare = true; public static shouldShare = true;
public static requireCredential = true; public static requireCredential = true;
private withReplies: boolean; private withReplies: boolean;
private withFiles: boolean;
constructor( constructor(
private noteEntityService: NoteEntityService, private noteEntityService: NoteEntityService,
@ -26,6 +27,7 @@ class HomeTimelineChannel extends Channel {
@bindThis @bindThis
public async init(params: any) { public async init(params: any) {
this.withReplies = params.withReplies as boolean; this.withReplies = params.withReplies as boolean;
this.withFiles = params.withFiles as boolean;
this.subscriber.on('notesStream', this.onNote); this.subscriber.on('notesStream', this.onNote);
} }
@ -42,6 +44,9 @@ class HomeTimelineChannel extends Channel {
// Ignore notes from instances the user has muted // Ignore notes from instances the user has muted
if (isInstanceMuted(note, new Set<string>(this.userProfile!.mutedInstances ?? []))) return; if (isInstanceMuted(note, new Set<string>(this.userProfile!.mutedInstances ?? []))) return;
// ファイルを含まない投稿は除外
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
if (['followers', 'specified'].includes(note.visibility)) { if (['followers', 'specified'].includes(note.visibility)) {
note = await this.noteEntityService.pack(note.id, this.user!, { note = await this.noteEntityService.pack(note.id, this.user!, {
detail: true, detail: true,

View file

@ -14,6 +14,7 @@ class HybridTimelineChannel extends Channel {
public static shouldShare = true; public static shouldShare = true;
public static requireCredential = true; public static requireCredential = true;
private withReplies: boolean; private withReplies: boolean;
private withFiles: boolean;
constructor( constructor(
private metaService: MetaService, private metaService: MetaService,
@ -33,6 +34,7 @@ class HybridTimelineChannel extends Channel {
if (!policies.ltlAvailable) return; if (!policies.ltlAvailable) return;
this.withReplies = params.withReplies as boolean; this.withReplies = params.withReplies as boolean;
this.withFiles = params.withFiles as boolean;
// Subscribe events // Subscribe events
this.subscriber.on('notesStream', this.onNote); this.subscriber.on('notesStream', this.onNote);
@ -51,6 +53,9 @@ class HybridTimelineChannel extends Channel {
(note.channelId != null && this.followingChannels.has(note.channelId)) (note.channelId != null && this.followingChannels.has(note.channelId))
)) return; )) return;
// ファイルを含まない投稿は除外
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
if (['followers', 'specified'].includes(note.visibility)) { if (['followers', 'specified'].includes(note.visibility)) {
note = await this.noteEntityService.pack(note.id, this.user!, { note = await this.noteEntityService.pack(note.id, this.user!, {
detail: true, detail: true,

View file

@ -13,6 +13,7 @@ class LocalTimelineChannel extends Channel {
public static shouldShare = true; public static shouldShare = true;
public static requireCredential = false; public static requireCredential = false;
private withReplies: boolean; private withReplies: boolean;
private withFiles: boolean;
constructor( constructor(
private metaService: MetaService, private metaService: MetaService,
@ -32,6 +33,7 @@ class LocalTimelineChannel extends Channel {
if (!policies.ltlAvailable) return; if (!policies.ltlAvailable) return;
this.withReplies = params.withReplies as boolean; this.withReplies = params.withReplies as boolean;
this.withFiles = params.withFiles as boolean;
// Subscribe events // Subscribe events
this.subscriber.on('notesStream', this.onNote); this.subscriber.on('notesStream', this.onNote);
@ -43,6 +45,9 @@ class LocalTimelineChannel extends Channel {
if (note.visibility !== 'public') return; if (note.visibility !== 'public') return;
if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; if (note.channelId != null && !this.followingChannels.has(note.channelId)) return;
// ファイルを含まない投稿は除外
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
// リプライなら再pack // リプライなら再pack
if (note.replyId != null) { if (note.replyId != null) {
note.reply = await this.noteEntityService.pack(note.replyId, this.user, { note.reply = await this.noteEntityService.pack(note.replyId, this.user, {

View file

@ -82,6 +82,17 @@ if (props.src === 'antenna') {
withReplies: defaultStore.state.showTimelineReplies, withReplies: defaultStore.state.showTimelineReplies,
}); });
connection.on('note', prepend); connection.on('note', prepend);
} else if (props.src === 'media') {
endpoint = 'notes/hybrid-timeline';
query = {
withFiles: true,
withReplies: defaultStore.state.showTimelineReplies,
};
connection = stream.useChannel('hybridTimeline', {
withFiles: true,
withReplies: defaultStore.state.showTimelineReplies,
});
connection.on('note', prepend);
} else if (props.src === 'social') { } else if (props.src === 'social') {
endpoint = 'notes/hybrid-timeline'; endpoint = 'notes/hybrid-timeline';
query = { query = {

View file

@ -24,11 +24,21 @@
</div> </div>
<FormSection> <FormSection>
<div class="_formLinks"> <div class="_formLinks">
<FormLink to="https://github.com/misskey-dev/misskey" external> <FormLink to="https://github.com/Misskey-art/misskey" external>
<template #icon><i class="ti ti-code"></i></template> <template #icon><i class="ti ti-code"></i></template>
{{ i18n.ts._aboutMisskey.source }} {{ i18n.ts._aboutMisskey.source }}
<template #suffix>GitHub</template> <template #suffix>GitHub</template>
</FormLink> </FormLink>
<FormLink to="https://github.com/misskey-dev/misskey" external>
<template #icon><i class="ti ti-code"></i></template>
{{ i18n.ts._aboutMisskey.originalSource }}
<template #suffix>GitHub</template>
</FormLink>
<FormLink to="https://github.com/misskeyIO/misskey" external>
<template #icon><i class="ti ti-code"></i></template>
{{ i18n.ts._aboutMisskey.ioSource }}
<template #suffix>GitHub</template>
</FormLink>
<FormLink to="https://crowdin.com/project/misskey" external> <FormLink to="https://crowdin.com/project/misskey" external>
<template #icon><i class="ti ti-language-hiragana"></i></template> <template #icon><i class="ti ti-language-hiragana"></i></template>
{{ i18n.ts._aboutMisskey.translation }} {{ i18n.ts._aboutMisskey.translation }}

View file

@ -128,6 +128,11 @@ const headerTabs = $computed(() => [{
title: i18n.ts._timelines.local, title: i18n.ts._timelines.local,
icon: 'ti ti-planet', icon: 'ti ti-planet',
iconOnly: true, iconOnly: true,
}, {
key: 'media',
title: i18n.ts._timelines.media,
icon: 'ti ti-photo',
iconOnly: true,
}, { }, {
key: 'social', key: 'social',
title: i18n.ts._timelines.social, title: i18n.ts._timelines.social,

View file

@ -24,7 +24,7 @@ export type Column = {
channelId?: string; channelId?: string;
roleId?: string; roleId?: string;
includingTypes?: typeof notificationTypes[number][]; includingTypes?: typeof notificationTypes[number][];
tl?: 'home' | 'local' | 'social' | 'global'; tl?: 'home' | 'local' | 'media' | 'social' | 'global';
}; };
export const deckStore = markRaw(new Storage('deck', { export const deckStore = markRaw(new Storage('deck', {

View file

@ -4,6 +4,7 @@
<i v-if="column.tl === 'home'" class="ti ti-home"></i> <i v-if="column.tl === 'home'" class="ti ti-home"></i>
<i v-else-if="column.tl === 'local'" class="ti ti-planet"></i> <i v-else-if="column.tl === 'local'" class="ti ti-planet"></i>
<i v-else-if="column.tl === 'social'" class="ti ti-rocket"></i> <i v-else-if="column.tl === 'social'" class="ti ti-rocket"></i>
<i v-else-if="column.tl === 'media'" class="ti ti-photo"></i>
<i v-else-if="column.tl === 'global'" class="ti ti-whirl"></i> <i v-else-if="column.tl === 'global'" class="ti ti-whirl"></i>
<span style="margin-left: 8px;">{{ column.name }}</span> <span style="margin-left: 8px;">{{ column.name }}</span>
</template> </template>
@ -56,6 +57,8 @@ async function setType() {
value: 'home' as const, text: i18n.ts._timelines.home, value: 'home' as const, text: i18n.ts._timelines.home,
}, { }, {
value: 'local' as const, text: i18n.ts._timelines.local, value: 'local' as const, text: i18n.ts._timelines.local,
}, {
value: 'media' as const, text: i18n.ts._timelines.media,
}, { }, {
value: 'social' as const, text: i18n.ts._timelines.social, value: 'social' as const, text: i18n.ts._timelines.social,
}, { }, {

View file

@ -117,6 +117,10 @@ const choose = async (ev) => {
text: i18n.ts._timelines.local, text: i18n.ts._timelines.local,
icon: 'ti ti-planet', icon: 'ti ti-planet',
action: () => { setSrc('local'); }, action: () => { setSrc('local'); },
}, {
text: i18n.ts._timelines.media,
icon: 'ti ti-photo',
action: () => { setSrc('media'); },
}, { }, {
text: i18n.ts._timelines.social, text: i18n.ts._timelines.social,
icon: 'ti ti-rocket', icon: 'ti ti-rocket',