feat: メディアタイムラインを輸入 (#103)
* メディアタイムラインの実装 * refactor(stream): ストリーミングにwithFilesオプションを実装 --------- Co-authored-by: tar_bin <tar.bin.master@gmail.com>
This commit is contained in:
parent
bf06af04c8
commit
6d3f64f606
|
@ -1882,6 +1882,7 @@ _instanceCharts:
|
|||
_timelines:
|
||||
home: "Home"
|
||||
local: "Local"
|
||||
media: "Media"
|
||||
social: "Social"
|
||||
global: "Global"
|
||||
_play:
|
||||
|
|
1
locales/index.d.ts
vendored
1
locales/index.d.ts
vendored
|
@ -2012,6 +2012,7 @@ export interface Locale {
|
|||
"_timelines": {
|
||||
"home": string;
|
||||
"local": string;
|
||||
"media": string;
|
||||
"social": string;
|
||||
"global": string;
|
||||
};
|
||||
|
|
|
@ -1928,6 +1928,7 @@ _instanceCharts:
|
|||
_timelines:
|
||||
home: "ホーム"
|
||||
local: "ローカル"
|
||||
media: "メディア"
|
||||
social: "ソーシャル"
|
||||
global: "グローバル"
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ class GlobalTimelineChannel extends Channel {
|
|||
public static shouldShare = true;
|
||||
public static requireCredential = false;
|
||||
private withReplies: boolean;
|
||||
private withFiles: boolean;
|
||||
|
||||
constructor(
|
||||
private metaService: MetaService,
|
||||
|
@ -33,6 +34,7 @@ class GlobalTimelineChannel extends Channel {
|
|||
if (!policies.gtlAvailable) return;
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
this.withFiles = params.withFiles as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
@ -43,6 +45,9 @@ class GlobalTimelineChannel extends Channel {
|
|||
if (note.visibility !== 'public') return;
|
||||
if (note.channelId != null) return;
|
||||
|
||||
// ファイルを含まない投稿は除外
|
||||
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
|
||||
|
||||
// リプライなら再pack
|
||||
if (note.replyId != null) {
|
||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
|
||||
|
|
|
@ -12,6 +12,7 @@ class HomeTimelineChannel extends Channel {
|
|||
public static shouldShare = true;
|
||||
public static requireCredential = true;
|
||||
private withReplies: boolean;
|
||||
private withFiles: boolean;
|
||||
|
||||
constructor(
|
||||
private noteEntityService: NoteEntityService,
|
||||
|
@ -26,6 +27,7 @@ class HomeTimelineChannel extends Channel {
|
|||
@bindThis
|
||||
public async init(params: any) {
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
this.withFiles = params.withFiles as boolean;
|
||||
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
}
|
||||
|
@ -42,6 +44,9 @@ class HomeTimelineChannel extends Channel {
|
|||
// Ignore notes from instances the user has muted
|
||||
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)) {
|
||||
note = await this.noteEntityService.pack(note.id, this.user!, {
|
||||
detail: true,
|
||||
|
|
|
@ -14,6 +14,7 @@ class HybridTimelineChannel extends Channel {
|
|||
public static shouldShare = true;
|
||||
public static requireCredential = true;
|
||||
private withReplies: boolean;
|
||||
private withFiles: boolean;
|
||||
|
||||
constructor(
|
||||
private metaService: MetaService,
|
||||
|
@ -33,6 +34,7 @@ class HybridTimelineChannel extends Channel {
|
|||
if (!policies.ltlAvailable) return;
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
this.withFiles = params.withFiles as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
@ -51,6 +53,9 @@ class HybridTimelineChannel extends Channel {
|
|||
(note.channelId != null && this.followingChannels.has(note.channelId))
|
||||
)) return;
|
||||
|
||||
// ファイルを含まない投稿は除外
|
||||
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
|
||||
|
||||
if (['followers', 'specified'].includes(note.visibility)) {
|
||||
note = await this.noteEntityService.pack(note.id, this.user!, {
|
||||
detail: true,
|
||||
|
|
|
@ -13,6 +13,7 @@ class LocalTimelineChannel extends Channel {
|
|||
public static shouldShare = true;
|
||||
public static requireCredential = false;
|
||||
private withReplies: boolean;
|
||||
private withFiles: boolean;
|
||||
|
||||
constructor(
|
||||
private metaService: MetaService,
|
||||
|
@ -32,6 +33,7 @@ class LocalTimelineChannel extends Channel {
|
|||
if (!policies.ltlAvailable) return;
|
||||
|
||||
this.withReplies = params.withReplies as boolean;
|
||||
this.withFiles = params.withFiles as boolean;
|
||||
|
||||
// Subscribe events
|
||||
this.subscriber.on('notesStream', this.onNote);
|
||||
|
@ -43,6 +45,9 @@ class LocalTimelineChannel extends Channel {
|
|||
if (note.visibility !== 'public') return;
|
||||
if (note.channelId != null && !this.followingChannels.has(note.channelId)) return;
|
||||
|
||||
// ファイルを含まない投稿は除外
|
||||
if (this.withFiles && (note.files === undefined || note.files.length === 0)) return;
|
||||
|
||||
// リプライなら再pack
|
||||
if (note.replyId != null) {
|
||||
note.reply = await this.noteEntityService.pack(note.replyId, this.user, {
|
||||
|
|
|
@ -82,6 +82,17 @@ if (props.src === 'antenna') {
|
|||
withReplies: defaultStore.state.showTimelineReplies,
|
||||
});
|
||||
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') {
|
||||
endpoint = 'notes/hybrid-timeline';
|
||||
query = {
|
||||
|
|
|
@ -128,6 +128,11 @@ const headerTabs = $computed(() => [{
|
|||
title: i18n.ts._timelines.local,
|
||||
icon: 'ti ti-planet',
|
||||
iconOnly: true,
|
||||
}, {
|
||||
key: 'media',
|
||||
title: i18n.ts._timelines.media,
|
||||
icon: 'ti ti-photo',
|
||||
iconOnly: true,
|
||||
}, {
|
||||
key: 'social',
|
||||
title: i18n.ts._timelines.social,
|
||||
|
|
|
@ -24,7 +24,7 @@ export type Column = {
|
|||
channelId?: string;
|
||||
roleId?: string;
|
||||
includingTypes?: typeof notificationTypes[number][];
|
||||
tl?: 'home' | 'local' | 'social' | 'global';
|
||||
tl?: 'home' | 'local' | 'media' | 'social' | 'global';
|
||||
};
|
||||
|
||||
export const deckStore = markRaw(new Storage('deck', {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<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 === '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>
|
||||
<span style="margin-left: 8px;">{{ column.name }}</span>
|
||||
</template>
|
||||
|
@ -56,6 +57,8 @@ async function setType() {
|
|||
value: 'home' as const, text: i18n.ts._timelines.home,
|
||||
}, {
|
||||
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,
|
||||
}, {
|
||||
|
|
|
@ -117,6 +117,10 @@ const choose = async (ev) => {
|
|||
text: i18n.ts._timelines.local,
|
||||
icon: 'ti ti-planet',
|
||||
action: () => { setSrc('local'); },
|
||||
}, {
|
||||
text: i18n.ts._timelines.media,
|
||||
icon: 'ti ti-photo',
|
||||
action: () => { setSrc('media'); },
|
||||
}, {
|
||||
text: i18n.ts._timelines.social,
|
||||
icon: 'ti ti-rocket',
|
||||
|
|
Loading…
Reference in a new issue