Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.

Commit 5526713

Browse files
committed
いい感じに
1 parent e3a1a80 commit 5526713

File tree

10 files changed

+212
-170
lines changed

10 files changed

+212
-170
lines changed

locales/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export interface Locale extends ILocale {
4040
* リセット
4141
*/
4242
"reset": string;
43+
/**
44+
* {fileCount}つのファイルを削除します。
45+
*/
46+
"driveMultiFileDeleteConfirm": ParameterizedString<"fileCount">;
4347
/**
4448
* 通知
4549
*/

locales/ja-JP.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ poweredByType4nyDescription: "{name}は、オープンソースのプラット
66
monthAndDay: "{month}月 {day}日"
77
search: "検索"
88
reset: "リセット"
9+
driveMultiFileDeleteConfirm: "{fileCount}つのファイルを削除します。"
910
notifications: "通知"
1011
username: "ユーザー名"
1112
password: "パスワード"

packages/backend/src/core/FanoutTimelineService.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ export type FanoutTimelineName = (
3737

3838
// role timelines
3939
| `roleTimeline:${string}` // any notes are included
40-
);
41-
4240
| `remoteLocalTimeline:${string}`
41+
);
4342

4443
@Injectable()
4544
export class FanoutTimelineService {

packages/backend/src/server/api/endpoints/users/lists/list.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const paramDef = {
5151
type: 'object',
5252
properties: {
5353
userId: { type: 'string', format: 'misskey:id' },
54-
publicAll: { type: 'boolean', nullable: false },
54+
publicAll: { type: 'boolean' },
5555
},
5656
required: [],
5757
} as const;
@@ -68,7 +68,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
6868
private userListEntityService: UserListEntityService,
6969
) {
7070
super(meta, paramDef, async (ps, me) => {
71-
if (!ps.publicAll ) {
71+
if (!ps.publicAll) {
7272
if (typeof ps.userId !== 'undefined') {
7373
const user = await this.usersRepository.findOneBy({ id: ps.userId });
7474
if (user === null) throw new ApiError(meta.errors.noSuchUser);

packages/frontend-shared/js/emojilist.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ export type UnicodeEmojiDef = {
1111
};
1212

1313
// initial converted from https://github.com/muan/emojilib/commit/242fe68be86ed6536843b83f7e32f376468b38fb
14-
import _emojilist from './emojilist.json';
14+
import _emojilist from './emojilist.json' with { type: "json" };
1515

1616
async function loadEmojiList() {
1717
let emojilistData = _emojilist;
1818

1919
if (!emojilistData) {
20-
emojilistData = (await import('./emojilist.json')).default;
20+
emojilistData = (await import('./emojilist.json', { with: { type: "json" } })).default;
2121
}
2222

2323
return emojilistData;

packages/frontend/src/pages/timeline.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import { miLocalStorage } from '@/local-storage.js';
4848
import { availableBasicTimelines, hasWithReplies, isAvailableBasicTimeline, isBasicTimeline, basicTimelineIconClass } from '@/timelines.js';
4949
import { prefer } from '@/preferences.js';
5050
import { ui } from '@@/js/config.js';
51-
import { timelineHeaderItemDef } from '@/timeline-header';
51+
import { timelineHeaderItemDef, updateTimelineHeaderItems } from '@/timeline-header';
5252
const XPostForm = defineAsyncComponent(() => import('@/components/XPostForm.vue'));
5353
5454
const tlComponent = useTemplateRef('tlComponent');
@@ -214,10 +214,12 @@ function switchTlIfNeeded() {
214214
}
215215
}
216216
217-
onMounted(() => {
217+
onMounted(async () => {
218+
await updateTimelineHeaderItems();
218219
switchTlIfNeeded();
219220
});
220-
onActivated(() => {
221+
onActivated(async () => {
222+
await updateTimelineHeaderItems();
221223
switchTlIfNeeded();
222224
});
223225

packages/frontend/src/timeline-header.ts

Lines changed: 77 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ type TimelineHeaderItemsDef = {
3535
iconOnly?: boolean; // わからん
3636
};
3737

38-
const lists = await userListsCache.fetch();
39-
const userChannels = await userChannelsCache.fetch();
40-
const userChannelFollowings = await userChannelFollowingsCache.fetch();
41-
const userFavoriteLists = await userFavoriteListsCache.fetch();
42-
const antenna = await antennasCache.fetch();
43-
4438
export const timelineHeaderItemDef = reactive<Partial<Record<TimelineHeaderItem, TimelineHeaderItemsDef>>>({
4539
home: {
4640
title: i18n.ts._timelines.home,
@@ -83,45 +77,82 @@ export const timelineHeaderItemDef = reactive<Partial<Record<TimelineHeaderItem,
8377
title: i18n.ts.channel,
8478
iconOnly: false,
8579
},
86-
...lists.reduce((acc, l) => {
87-
acc['list:' + l.id] = {
88-
title: i18n.ts.lists + ':' + l.name,
89-
icon: 'ti ti-star',
90-
iconOnly: false,
91-
};
92-
return acc;
93-
}, {}),
94-
...userChannels.reduce((acc, l) => {
95-
acc['channel:' + l.id] = {
96-
title: i18n.ts.channel + ':' + l.name,
97-
icon: 'ti ti-star',
98-
iconOnly: false,
99-
};
100-
return acc;
101-
}, {}),
102-
...userChannelFollowings.reduce((acc, l) => {
103-
acc['channel:' + l.id] = {
104-
title: i18n.ts.channel + ':' + l.name,
105-
icon: 'ti ti-star',
106-
iconOnly: false,
107-
};
108-
return acc;
109-
}, {}),
110-
...userFavoriteLists.reduce((acc, l) => {
111-
acc['channel:' + l.id] = {
112-
title: i18n.ts.channel + ':' + l.name,
113-
icon: 'ti ti-star',
114-
iconOnly: false,
115-
};
116-
return acc;
117-
}, {}),
118-
...antenna.reduce((acc, l) => {
119-
acc['antenna:' + l.id] = {
120-
title: i18n.ts.antennas + ':' + l.name,
121-
icon: 'ti ti-star',
122-
iconOnly: false,
123-
};
124-
return acc;
125-
}, {}),
12680
});
12781

82+
export async function updateTimelineHeaderItems() {
83+
try {
84+
const [lists, userChannels, userChannelFollowings, userFavoriteLists, antenna] = await Promise.all([
85+
userListsCache.fetch(),
86+
userChannelsCache.fetch(),
87+
userChannelFollowingsCache.fetch(),
88+
userFavoriteListsCache.fetch(),
89+
antennasCache.fetch(),
90+
]);
91+
92+
// Clear existing dynamic items
93+
for (const key in timelineHeaderItemDef) {
94+
if (key.startsWith('list:') || key.startsWith('channel:') || key.startsWith('antenna:')) {
95+
delete timelineHeaderItemDef[key];
96+
}
97+
}
98+
99+
// Add lists
100+
lists.forEach(l => {
101+
timelineHeaderItemDef[`list:${l.id}`] = {
102+
title: `${i18n.ts.lists}:${l.name}`,
103+
icon: 'ti ti-star',
104+
iconOnly: false,
105+
};
106+
});
107+
108+
// Add user channels
109+
userChannels.forEach(l => {
110+
timelineHeaderItemDef[`channel:${l.id}`] = {
111+
title: `${i18n.ts.channel}:${l.name}`,
112+
icon: 'ti ti-device-tv',
113+
iconOnly: false,
114+
};
115+
});
116+
117+
// Add channel followings
118+
userChannelFollowings.forEach(l => {
119+
// Only add if not already added by userChannels
120+
if (!timelineHeaderItemDef[`channel:${l.id}`]) {
121+
timelineHeaderItemDef[`channel:${l.id}`] = {
122+
title: `${i18n.ts.channel}:${l.name}`,
123+
icon: 'ti ti-device-tv',
124+
iconOnly: false,
125+
};
126+
}
127+
});
128+
129+
// Add favorite lists (these should probably be lists, not channels)
130+
userFavoriteLists.forEach(l => {
131+
// This seems like a bug - favorite lists should use 'list:' prefix
132+
if (!timelineHeaderItemDef[`list:${l.id}`]) {
133+
timelineHeaderItemDef[`list:${l.id}`] = {
134+
title: `${i18n.ts.lists}:${l.name}`,
135+
icon: 'ti ti-star',
136+
iconOnly: false,
137+
};
138+
}
139+
});
140+
141+
// Add antennas
142+
antenna.forEach(l => {
143+
timelineHeaderItemDef[`antenna:${l.id}`] = {
144+
title: `${i18n.ts.antennas}:${l.name}`,
145+
icon: 'ti ti-antenna',
146+
iconOnly: false,
147+
};
148+
});
149+
} catch (error) {
150+
console.error('Failed to update timeline header items:', error);
151+
}
152+
}
153+
154+
// Initialize on first load if user is logged in
155+
if ($i) {
156+
updateTimelineHeaderItems();
157+
}
158+

packages/frontend/src/ui/twilike.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ SPDX-License-Identifier: AGPL-3.0-only
8787

8888
<script lang="ts" setup>
8989
import { defineAsyncComponent, onMounted, provide, ref, computed, shallowRef, watch } from 'vue';
90+
import { instanceName, ui } from '@@/js/config.js';
9091
import XSidebar from './twilike.sidebar.vue';
9192
import XCommon from './_common_/common.vue';
92-
import { instanceName, ui } from '@/config.js';
93+
import type { PageMetadata } from '@/page.js';
9394
import * as os from '@/os.js';
9495
import { definePage, provideMetadataReceiver, provideReactiveMetadata } from '@/page.js';
95-
import type { PageMetadata } from '@/page.js';
9696
import { store } from '@/store.js';
9797
import { i18n } from '@/i18n.js';
9898
import { miLocalStorage } from '@/local-storage.js';

packages/frontend/src/utility/get-drive-file-menu.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,27 @@ async function deleteFile(file: Misskey.entities.DriveFile) {
8787

8888
globalEvents.emit('driveFilesDeleted', [file]);
8989
}
90+
9091
async function MultideleteFile(files: Misskey.entities.DriveFile[] | null) {
92+
if (!files || files.length === 0) return;
93+
9194
const { canceled } = await os.confirm({
9295
type: 'warning',
93-
text: i18n.t('driveMultiFileDeleteConfirm', { name: files.length }),
96+
text: i18n.tsx.driveMultiFileDeleteConfirm({ fileCounts: files.length }),
9497
});
9598

9699
if (canceled) return;
97-
files.forEach((e)=>{
100+
files.forEach((e) => {
98101
misskeyApi('drive/files/delete', {
99102
fileId: e.id,
100-
});
101-
})
103+
});
104+
});
102105
}
103-
function isSensitive(files: Misskey.entities.DriveFile[] | null ,sensitive:boolean) {
104-
files.forEach((e)=>{
106+
107+
function isSensitive(files: Misskey.entities.DriveFile[] | null, sensitive: boolean) {
108+
if (!files || files.length === 0) return;
109+
110+
files.forEach((e) => {
105111
misskeyApi('drive/files/update', {
106112
fileId: e.id,
107113
isSensitive: sensitive,
@@ -112,9 +118,9 @@ function isSensitive(files: Misskey.entities.DriveFile[] | null ,sensitive:boole
112118
text: err.message,
113119
});
114120
});
115-
})
116-
121+
});
117122
}
123+
118124
export function getDriveFileMenu(file: Misskey.entities.DriveFile, folder?: Misskey.entities.DriveFolder | null): MenuItem[] {
119125
const isImage = file.type.startsWith('image/');
120126

@@ -179,16 +185,15 @@ export function getDriveFileMenu(file: Misskey.entities.DriveFile, folder?: Miss
179185

180186
return menuItems;
181187
}
182-
export function getDriveMultiFileMenu(files: string[] & boolean): MenuItem[] {
183-
let menu;
184-
menu = [{
185-
text: i18n.ts.unmarkAsSensitive,
188+
export function getDriveMultiFileMenu(files: Misskey.entities.DriveFile[]): MenuItem[] {
189+
const menu = [{
190+
text: i18n.ts.unmarkAsSensitive,
186191
icon: 'ti ti-eye',
187-
action: () => isSensitive(files,false),
188-
},{
192+
action: () => isSensitive(files, false),
193+
}, {
189194
text: i18n.ts.markAsSensitive,
190-
icon: 'ti ti-eye-exclamation',
191-
action: () => isSensitive(files,true),
195+
icon: 'ti ti-eye-exclamation',
196+
action: () => isSensitive(files, true),
192197
}, {
193198
text: i18n.ts.delete,
194199
icon: 'ti ti-trash',

0 commit comments

Comments
 (0)