Skip to content

Commit 0c38ee2

Browse files
committed
feat: ✨ kemono 支持在列表页多选加载
1 parent f92dc49 commit 0c38ee2

22 files changed

Lines changed: 811 additions & 103 deletions

locales/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"jump_prev": "Jump to previous chap",
5454
"jump_to_end": "Jump to the last page",
5555
"jump_to_home": "Jump to the first page",
56+
"multi_select_load": "Multi-select load",
5657
"page_down": "Turn the page to the down",
5758
"page_up": "Turn the page to the up",
5859
"reload_current_error_img": "Reload current error image",
@@ -89,11 +90,13 @@
8990
"img_loading": "Image loading",
9091
"interval": "interval",
9192
"loading_img": "Loading image",
93+
"multi_select_mode": "Multi-select mode",
9294
"none": "None",
9395
"or": "or",
9496
"other": "Other",
9597
"page_range": "Please enter the page range.:\n (e.g., 1, 3-5, 9-)",
9698
"read_mode": "Reading mode",
99+
"selected": "Selected",
97100
"setting": "Settings"
98101
},
99102
"pwa": {

locales/hu.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"jump_prev": "Ugrás az előző fejezetre",
5454
"jump_to_end": "Ugrás az utolsó oldalra",
5555
"jump_to_home": "Ugrás az első oldalra",
56+
"multi_select_load": "Többkijelölés betöltése",
5657
"page_down": "Lapozás lefelé",
5758
"page_up": "Lapozás felfelé",
5859
"reload_current_error_img": "Jelenlegi hibás kép újratöltése",
@@ -89,11 +90,13 @@
8990
"img_loading": "Kép betöltése",
9091
"interval": "intervallum",
9192
"loading_img": "Kép betöltése",
93+
"multi_select_mode": "Többkijelölés mód",
9294
"none": "Nincs",
9395
"or": "vagy",
9496
"other": "egyéb",
9597
"page_range": "Kérlek add meg az oldaltartományt:\n(például: 1, 3-5, 9-)",
9698
"read_mode": "Olvasó mód",
99+
"selected": "Kiválasztva",
97100
"setting": "Beállítások"
98101
},
99102
"pwa": {

locales/ru.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"jump_prev": "Перейти к предыдущей главе",
5454
"jump_to_end": "Перейти к последней странице",
5555
"jump_to_home": "Перейти к первой странице",
56+
"multi_select_load": "Множественная загрузка",
5657
"page_down": "Перелистнуть страницу вниз",
5758
"page_up": "Перелистнуть страницу вверх",
5859
"reload_current_error_img": "Перезагрузить текущее ошибочное изображение",
@@ -89,11 +90,13 @@
8990
"img_loading": "Изображение загружается",
9091
"interval": "интервал",
9192
"loading_img": "Загрузка изображения",
93+
"multi_select_mode": "Режим множественного выбора",
9294
"none": "Отсутствует",
9395
"or": "или",
9496
"other": "Другое",
9597
"page_range": "Введите диапазон страниц.:\n (например, 1, 3-5, 9-)",
9698
"read_mode": "Режим чтения",
99+
"selected": "Выбрано",
97100
"setting": "Настройки"
98101
},
99102
"pwa": {

locales/ta.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"jump_prev": "முந்தைய அத்தியாயத்திற்குத் தாவு",
5454
"jump_to_end": "இறுதிவரை குதிக்கவும்",
5555
"jump_to_home": "முகப்புப்பக்கத்திற்கு செல்லவும்",
56+
"multi_select_load": "பல தேர்வு ஏற்றம்",
5657
"page_down": "பக்கங்கள் கீழே",
5758
"page_up": "பக்கங்கள் மேலே",
5859
"reload_current_error_img": "தற்போதைய பிழை படத்தை மீண்டும் ஏற்றவும்",
@@ -89,11 +90,13 @@
8990
"img_loading": "படம் ஏற்றுகிறது",
9091
"interval": "இடைவெளி",
9192
"loading_img": "படத்தை ஏற்றவும்",
93+
"multi_select_mode": "பல தேர்வு பயன்முறை",
9294
"none": "இல்லை",
9395
"or": "அல்லது",
9496
"other": "மற்றொன்று",
9597
"page_range": "பக்க எண் வரம்பை உள்ளிடவும்:\n (எடுத்துக்காட்டாக: 1, 3-5, 9-))",
9698
"read_mode": "படித்தல் பயன்முறை",
99+
"selected": "தேர்ந்தெடுக்கப்பட்டது",
97100
"setting": "அமைக்கவும்"
98101
},
99102
"pwa": {

locales/zh.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"jump_prev": "跳至上一话",
5454
"jump_to_end": "跳至尾页",
5555
"jump_to_home": "跳至首页",
56+
"multi_select_load": "多选加载",
5657
"page_down": "向下翻页",
5758
"page_up": "向上翻页",
5859
"reload_current_error_img": "重载当前错误图片",
@@ -89,11 +90,13 @@
8990
"img_loading": "图片加载中",
9091
"interval": "间隔",
9192
"loading_img": "加载图片中",
93+
"multi_select_mode": "多选模式",
9294
"none": "",
9395
"or": "",
9496
"other": "其他",
9597
"page_range": "请输入页码范围:\n(例如:1, 3-5, 9-)",
9698
"read_mode": "阅读模式",
99+
"selected": "已选中",
97100
"setting": "设置"
98101
},
99102
"pwa": {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"dependencies": {
3333
"@material-design-icons/svg": "^0.14.15",
3434
"@placemarkio/flat-drop-files": "^1.0.2",
35+
"@solid-primitives/map": "^0.7.3",
3536
"@solid-primitives/scheduled": "^1.5.2",
3637
"@solid-primitives/set": "^0.7.2",
3738
"@tensorflow/tfjs": "^4.22.0",

pnpm-lock.yaml

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/Manga/actions/hotkeys.ts

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,35 +41,58 @@ export const hotkeysMap = createRootMemo(() =>
4141
),
4242
);
4343

44+
const actionsMap: Record<
45+
'bubble' | 'capture',
46+
Record<string, (e: KeyboardEvent) => unknown> | null
47+
> = { bubble: null, capture: null };
48+
49+
const createKeydownHandler =
50+
(type: 'bubble' | 'capture') => (e: KeyboardEvent) => {
51+
const actions = actionsMap[type];
52+
if (!actions) return;
53+
54+
// 跳过输入框的键盘事件
55+
switch ((e.target as HTMLElement).tagName) {
56+
case 'INPUT':
57+
case 'TEXTAREA':
58+
return;
59+
}
60+
if ((e.target as HTMLElement).isContentEditable) return;
61+
62+
if (Reflect.has(actions, e.key) && actions[e.key](e) !== 1) {
63+
e.stopPropagation();
64+
e.preventDefault();
65+
e.stopImmediatePropagation();
66+
}
67+
68+
const hotkeyName = hotkeysMap()[getKeyboardCode(e)];
69+
if (Reflect.has(actions, hotkeyName) && actions[hotkeyName](e) !== 1) {
70+
e.stopPropagation();
71+
e.preventDefault();
72+
e.stopImmediatePropagation();
73+
}
74+
};
75+
76+
const handlers = {
77+
bubble: createKeydownHandler('bubble'),
78+
capture: createKeydownHandler('capture'),
79+
};
80+
4481
/** 监听快捷键 */
4582
export const listenHotkey = (
4683
actions: Record<string, (e: KeyboardEvent) => unknown>,
4784
capture?: boolean,
48-
) => {
49-
window.addEventListener(
50-
'keydown',
51-
(e) => {
52-
// 跳过输入框的键盘事件
53-
switch ((e.target as HTMLElement).tagName) {
54-
case 'INPUT':
55-
case 'TEXTAREA':
56-
return;
57-
}
58-
if ((e.target as HTMLElement).isContentEditable) return;
85+
): (() => void) => {
86+
const type = capture ? 'capture' : 'bubble';
5987

60-
if (Reflect.has(actions, e.key) && actions[e.key](e) !== 1) {
61-
e.stopPropagation();
62-
e.preventDefault();
63-
e.stopImmediatePropagation();
64-
}
88+
if (actionsMap[type]) Object.assign(actionsMap[type], actions);
89+
else {
90+
actionsMap[type] = { ...actions };
91+
window.addEventListener('keydown', handlers[type], { capture });
92+
}
6593

66-
const hotkeyName = hotkeysMap()[getKeyboardCode(e)];
67-
if (Reflect.has(actions, hotkeyName) && actions[hotkeyName](e) !== 1) {
68-
e.stopPropagation();
69-
e.preventDefault();
70-
e.stopImmediatePropagation();
71-
}
72-
},
73-
{ capture },
74-
);
94+
return () => {
95+
window.removeEventListener('keydown', handlers[type], { capture });
96+
actionsMap[type] = null;
97+
};
7598
};

src/helper/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './useCache';
88
export * from './useDrag';
99
export * from './useStore';
1010
export * from './useStyle';
11+
export * from './useMultiSelectMode';

src/helper/other.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ export const inRange = (min: number, val: number, max: number) =>
3636

3737
export const getFileName = (url: string) => url.match(/.+\/([^?]+)/)?.[1];
3838

39+
export const isString = (val: unknown): val is string =>
40+
typeof val === 'string';
41+
42+
export const isNumber = (val: unknown): val is number =>
43+
typeof val === 'number';
44+
3945
/** 判断两个数是否在指定误差范围内相等 */
4046
export const approx = (val: number, target: number, range = 1) =>
4147
Math.abs(target - val) <= range;

0 commit comments

Comments
 (0)