mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
Fix tag management view entering search flow
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## 4.9.9 - 2026-07-09
|
||||
|
||||
- 修复首页管理标签入口混入快捷搜索流程的问题,打开管理模式后不再显示“内容分类”“电影类型”“年份”等搜索快捷项。
|
||||
- 管理标签时隐藏电影/电视剧切换和推荐内容网格,让“完成 / 恢复默认 / 添加标签 / 标签列表”成为当前视图主体。
|
||||
- 标签管理列表改为可换行 chip 布局,并在管理模式下使用矩形拖拽排序策略,避免标签区域被横向滚动行挤压。
|
||||
- 新增标签管理视图回归测试,防止管理入口再次退化为搜索筛选界面。
|
||||
|
||||
## 4.9.8 - 2026-07-09
|
||||
|
||||
- 修复登录完成跳转后 Network 面板出现 `/api/user/config` 和 `/api/user/sync` 两个 400 请求的问题。
|
||||
|
||||
+12
-1
@@ -4,8 +4,19 @@
|
||||
"name": "KVideo",
|
||||
"branch": "main"
|
||||
},
|
||||
"currentVersion": "4.9.8",
|
||||
"currentVersion": "4.9.9",
|
||||
"releases": [
|
||||
{
|
||||
"version": "4.9.9",
|
||||
"publishedAt": "2026-07-09",
|
||||
"title": "修复管理标签入口误入搜索流程",
|
||||
"notes": [
|
||||
"首页管理标签模式现在会隐藏内容分类、电影类型、年份等快捷搜索项,避免用户打开标签管理时触发视频源搜索。",
|
||||
"管理标签时不再显示电影/电视剧切换和推荐内容网格,完成、恢复默认、添加标签和标签列表成为当前视图主体。",
|
||||
"标签 chip 在管理模式下改为可换行布局,并使用矩形拖拽排序策略,减少上方筛选内容对标签操作区的挤压。",
|
||||
"新增标签管理视图回归测试,锁定管理入口不应退化为搜索结果筛选界面。"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.9.8",
|
||||
"publishedAt": "2026-07-09",
|
||||
|
||||
@@ -58,6 +58,7 @@ export function PopularFeatures({ onSearch }: PopularFeaturesProps) {
|
||||
const [isRecommendSelected, setIsRecommendSelected] = useState(false);
|
||||
|
||||
const effectiveRecommendSelected = hasHistory && isRecommendSelected;
|
||||
const isTagManagementMode = showTagManager;
|
||||
|
||||
const {
|
||||
movies,
|
||||
@@ -92,10 +93,10 @@ export function PopularFeatures({ onSearch }: PopularFeaturesProps) {
|
||||
|
||||
return (
|
||||
<div className="animate-fade-in">
|
||||
<CategoryQuickSearch onSearch={onSearch} />
|
||||
{!isTagManagementMode && <CategoryQuickSearch onSearch={onSearch} />}
|
||||
|
||||
{/* Content Type Toggle (Capsule Liquid Glass - Fixed & Centered) */}
|
||||
{!effectiveRecommendSelected && (
|
||||
{!isTagManagementMode && !effectiveRecommendSelected && (
|
||||
<div className="mb-10 flex justify-center">
|
||||
<div className="relative w-80 p-1 bg-[var(--glass-bg)] border border-[var(--glass-border)] rounded-full grid grid-cols-2 backdrop-blur-2xl shadow-lg ring-1 ring-white/10 overflow-hidden">
|
||||
{/* Sliding Indicator */}
|
||||
@@ -146,24 +147,26 @@ export function PopularFeatures({ onSearch }: PopularFeaturesProps) {
|
||||
} : undefined}
|
||||
/>
|
||||
|
||||
{effectiveRecommendSelected ? (
|
||||
<MovieGrid
|
||||
movies={recommendMovies}
|
||||
loading={recommendLoading}
|
||||
hasMore={recommendHasMore}
|
||||
onMovieClick={handleMovieClick}
|
||||
prefetchRef={recommendPrefetchRef}
|
||||
loadMoreRef={recommendLoadMoreRef}
|
||||
/>
|
||||
) : (
|
||||
<MovieGrid
|
||||
movies={movies}
|
||||
loading={loading}
|
||||
hasMore={hasMore}
|
||||
onMovieClick={handleMovieClick}
|
||||
prefetchRef={prefetchRef}
|
||||
loadMoreRef={loadMoreRef}
|
||||
/>
|
||||
{!isTagManagementMode && (
|
||||
effectiveRecommendSelected ? (
|
||||
<MovieGrid
|
||||
movies={recommendMovies}
|
||||
loading={recommendLoading}
|
||||
hasMore={recommendHasMore}
|
||||
onMovieClick={handleMovieClick}
|
||||
prefetchRef={recommendPrefetchRef}
|
||||
loadMoreRef={recommendLoadMoreRef}
|
||||
/>
|
||||
) : (
|
||||
<MovieGrid
|
||||
movies={movies}
|
||||
loading={loading}
|
||||
hasMore={hasMore}
|
||||
onMovieClick={handleMovieClick}
|
||||
prefetchRef={prefetchRef}
|
||||
loadMoreRef={loadMoreRef}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -51,6 +51,7 @@ export function SortableTag({
|
||||
>
|
||||
<div className={`${showTagManager && !isDragging ? 'animate-jiggle' : ''}`}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onTagSelect(tag.id)}
|
||||
className={`
|
||||
px-6 py-2.5 text-sm font-semibold transition-all whitespace-nowrap rounded-[var(--radius-full)] cursor-pointer select-none
|
||||
@@ -64,6 +65,7 @@ export function SortableTag({
|
||||
</button>
|
||||
{showTagManager && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onTagDelete(tag.id);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { Icons } from '@/components/ui/Icon';
|
||||
|
||||
interface TagInputProps {
|
||||
newTagInput: string;
|
||||
onNewTagInputChange: (value: string) => void;
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
horizontalListSortingStrategy,
|
||||
rectSortingStrategy,
|
||||
} from '@dnd-kit/sortable';
|
||||
import { SortableTag, Tag } from './SortableTag';
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
@@ -115,12 +116,17 @@ export function TagList({
|
||||
>
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
className="mb-8 flex items-center gap-3 overflow-x-auto pb-3 pt-2 px-1 scrollbar-hide"
|
||||
className={`mb-8 flex items-center gap-3 pb-3 pt-2 px-1 scrollbar-hide ${
|
||||
showTagManager
|
||||
? 'flex-wrap overflow-visible'
|
||||
: 'overflow-x-auto'
|
||||
}`}
|
||||
>
|
||||
{/* Recommendation Tag — non-draggable, rendered before sortable tags */}
|
||||
{recommendTag && (
|
||||
<div className="relative flex-shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
onClick={recommendTag.onSelect}
|
||||
className={`
|
||||
px-6 py-2.5 text-sm font-semibold transition-all whitespace-nowrap rounded-[var(--radius-full)] cursor-pointer select-none flex items-center gap-1.5
|
||||
@@ -137,7 +143,7 @@ export function TagList({
|
||||
)}
|
||||
<SortableContext
|
||||
items={tags.map((t) => t.id)}
|
||||
strategy={horizontalListSortingStrategy}
|
||||
strategy={showTagManager ? rectSortingStrategy : horizontalListSortingStrategy}
|
||||
>
|
||||
{tags.map((tag) => (
|
||||
<SortableTag
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "kvideo",
|
||||
"version": "4.9.8",
|
||||
"version": "4.9.9",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "kvideo",
|
||||
"version": "4.9.8",
|
||||
"version": "4.9.9",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "kvideo",
|
||||
"version": "4.9.8",
|
||||
"version": "4.9.9",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "node scripts/next-with-lan-access.mjs dev",
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const projectRoot = process.cwd();
|
||||
|
||||
test('popular tag management mode stays out of quick search and discovery grids', () => {
|
||||
const source = readFileSync(
|
||||
join(projectRoot, 'components/home/PopularFeatures.tsx'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
assert.match(source, /const isTagManagementMode = showTagManager;/);
|
||||
assert.match(source, /!\s*isTagManagementMode && <CategoryQuickSearch/);
|
||||
assert.match(source, /!\s*isTagManagementMode && !effectiveRecommendSelected/);
|
||||
assert.match(source, /!\s*isTagManagementMode && \(/);
|
||||
});
|
||||
|
||||
test('tag management list uses wrapping chip layout instead of a horizontal search filter row', () => {
|
||||
const source = readFileSync(
|
||||
join(projectRoot, 'components/home/TagList.tsx'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
assert.match(source, /rectSortingStrategy/);
|
||||
assert.match(source, /showTagManager\s*\?\s*'flex-wrap overflow-visible'/);
|
||||
assert.match(source, /showTagManager \? rectSortingStrategy : horizontalListSortingStrategy/);
|
||||
});
|
||||
Reference in New Issue
Block a user