Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backgroundworker/prisma.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PrismaD1 } from '@prisma/adapter-d1';
import { config } from 'dotenv';
import { resolve } from 'path';

// 加载环境变量,优先读取.env.local,然后.env
// Load environment variables, preferring .env.local over .env
config({ path: resolve(process.cwd(), '../.env.local') });
config({ path: resolve(process.cwd(), '../.env') });

Expand Down
6 changes: 3 additions & 3 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { NextRequest, NextResponse } from 'next/server'
import { getCorsHeaders, getCorsOptionsHeaders } from './src/app/lib/cors'

export function middleware(request: NextRequest) {
// 处理所有API路由的CORS预检请求
// Handle CORS preflight requests for all API routes
if (request.method === 'OPTIONS' && request.nextUrl.pathname.startsWith('/api/')) {
return new NextResponse(null, {
status: 200,
headers: getCorsOptionsHeaders(request),
})
}

// 对于其他请求,继续处理
// Continue processing other requests
const response = NextResponse.next()

// 为所有API响应添加CORS头
// Add CORS headers to all API responses
if (request.nextUrl.pathname.startsWith('/api/')) {
const corsHeaders = getCorsHeaders(request)
Object.entries(corsHeaders).forEach(([key, value]) => {
Expand Down
2 changes: 1 addition & 1 deletion prisma.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PrismaD1 } from '@prisma/adapter-d1';
import { config } from 'dotenv';
import { resolve } from 'path';

// 加载环境变量,优先读取.env.local,然后.env
// Load environment variables, preferring .env.local over .env
config({ path: resolve(process.cwd(), '.env.local') });
config({ path: resolve(process.cwd(), '.env') });

Expand Down
6 changes: 3 additions & 3 deletions src/app/api/settings/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { NextRequest, NextResponse } from 'next/server';
import { withAuth } from '../../lib/auth';
import type { JWTPayload, SettingsResponse, UserSettings } from '../../types/api';

// 获取用户设置
// Fetch user settings
async function handleGetSettings(request: NextRequest, user: JWTPayload): Promise<Response> {
try {
// TODO: 从数据库获取用户设置
// 暂时返回默认设置
// TODO: Retrieve user settings from the database
// Temporarily return default settings
const settings: UserSettings = {
pomodoro_duration: 1500,
short_break_duration: 300,
Expand Down
16 changes: 8 additions & 8 deletions src/app/api/settings/sync/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@ import { NextRequest, NextResponse } from 'next/server';
import { withAuth } from '../../../lib/auth';
import type { JWTPayload, SyncOperationsRequest, SyncResponse, UserSettings } from '../../../types/api';

// 同步设置操作
// Sync settings operations
async function handleSyncSettings(request: NextRequest, user: JWTPayload): Promise<Response> {
try {
const { operations, lastSyncTime } = await request.json() as SyncOperationsRequest;
const userId = user.sub;

// TODO: 应用所有操作到数据库
// 暂时跳过数据库操作,只记录日志
// TODO: Apply all operations to the database
// Temporarily skip database operations; just log them
for (const operation of operations) {
console.log(`Processing settings operation: ${operation.type}`, {
payload: operation.payload,
timestamp: operation.timestamp,
userId
});

// 这里应该执行实际的数据库操作
// Actual database operations should be executed here
// await settingsService.applySettingsOperation(userId, operation);
}

// TODO: 获取更新后的设置
// 暂时返回默认设置
// TODO: Fetch updated settings
// Temporarily return default settings
const settings: UserSettings = {
pomodoro_duration: 1500,
short_break_duration: 300,
Expand All @@ -37,8 +37,8 @@ async function handleSyncSettings(request: NextRequest, user: JWTPayload): Promi
const response: SyncResponse = {
success: true,
data: {
conflicts: [], // 设置通常不会有冲突
serverOperations: [], // 暂时不需要返回服务端操作
conflicts: [], // Settings typically have no conflicts
serverOperations: [], // No server operations need to be returned for now
lastSyncTime: syncTime,
settings
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/user/profile/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
import { withAuth } from '../../../lib/auth';
import type { JWTPayload } from '../../../types/api';

// 获取用户信息
// Fetch user information
async function handleGetUserProfile(request: NextRequest, user: JWTPayload): Promise<Response> {
try {
return NextResponse.json({
Expand Down
10 changes: 5 additions & 5 deletions src/app/api/user/tokens/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getCorsHeaders } from '../../../lib/cors';

export async function GET(request: NextRequest) {
try {
// 验证JWT token
// Validate JWT token
const authHeader = request.headers.get('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return NextResponse.json(
Expand All @@ -30,7 +30,7 @@ export async function GET(request: NextRequest) {
);
}

// 从数据库获取用户信息
// Retrieve user information from the database
const db = getDb();
const user = await db.user.findUnique({
where: { id: decoded.sub }
Expand All @@ -46,7 +46,7 @@ export async function GET(request: NextRequest) {
);
}

// 检查token是否过期 (使用类型断言来访问可能的字段)
// Check whether the token has expired (using type assertion to access possible fields)
interface UserTokenFields {
googleAccessToken: string | null;
googleRefreshToken: string | null;
Expand All @@ -67,7 +67,7 @@ export async function GET(request: NextRequest) {
hasGoogleRefreshToken: !!userWithTokens.googleRefreshToken,
tokenExpiry: userWithTokens.googleTokenExpiry,
isTokenExpired,
// 不返回实际的token值,只返回是否存在
// Return only whether tokens exist, not their actual values
}
}, {
headers: getCorsHeaders(request)
Expand All @@ -85,7 +85,7 @@ export async function GET(request: NextRequest) {
}
}

// 处理CORS预检请求
// Handle CORS preflight requests
export async function OPTIONS(request: NextRequest) {
return new NextResponse(null, {
status: 200,
Expand Down
10 changes: 5 additions & 5 deletions src/app/componments/settings/Settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
@import '../common/forms.css';
@import '../common/states.css';

/* ===== 设置组件样式 ===== */
/* ===== Settings component styles ===== */

/* 设置界面样式 */
/* Settings interface styles */
.settings-modal {
background: var(--gradient-gray);
border-radius: var(--radius-2xl);
Expand Down Expand Up @@ -215,10 +215,10 @@
border-top: 1px solid var(--color-gray-200);
}

/* ===== 设置组件特定样式 ===== */
/* 使用通用按钮样式,并为设置组件添加特定样式 */
/* ===== Settings component specific styles ===== */
/* Use common button styles and add settings-specific styles */

/* ===== 响应式设计 ===== */
/* ===== Responsive design ===== */
@media (max-width: var(--breakpoint-tablet)) {
.settings-modal {
max-width: 95vw;
Expand Down
8 changes: 4 additions & 4 deletions src/app/componments/settings/settingsAPI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Settings API接口类型定义
// Settings API interface type definitions
export interface SettingsPayload {
value: number | boolean | string
}
Expand All @@ -7,7 +7,7 @@ export interface SettingsOperation {
type: string
payload: SettingsPayload
timestamp: string
id?: string // 本地操作ID,用于去重
id?: string // Local operation ID for deduplication
}

export interface SettingsSyncRequest {
Expand Down Expand Up @@ -161,7 +161,7 @@ class SettingsAPI {
}
}

// 单例管理
// Singleton management
let settingsAPIInstance: SettingsAPI | null = null;

export const getSettingsAPI = () => {
Expand All @@ -171,7 +171,7 @@ export const getSettingsAPI = () => {
return settingsAPIInstance;
};

// 为了向后兼容
// For backward compatibility
export const settingsAPI = {
get instance() {
return getSettingsAPI();
Expand Down
16 changes: 8 additions & 8 deletions src/app/componments/settings/settingsSyncManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import {
replaceSettings
} from '../clock/ClockSlice'

// Settings API适配器
// Settings API adapter
class SettingsAPIAdapter implements SyncAPI {
async syncOperations(operations: SyncOperation[], lastSyncTime: string | null) {
// 转换为SettingsOperation类型
// Convert to SettingsOperation type
const settingsOperations: SettingsOperation[] = operations.map(op => ({
type: op.type,
payload: op.payload as SettingsPayload,
Expand All @@ -38,12 +38,12 @@ class SettingsAPIAdapter implements SyncAPI {
}
}

// Settings操作处理器
// Settings operation handler
class SettingsOperationHandler implements OperationHandler {
applyOperation(operation: SyncOperation) {
const { type, payload } = operation

// 类型断言,因为我们知道不同操作类型的payload结构
// Type assertion since we know payload structures for different operation types
const typedPayload = payload as { value: number | boolean | string };

switch (type) {
Expand Down Expand Up @@ -71,7 +71,7 @@ class SettingsOperationHandler implements OperationHandler {
}

replaceData(data: unknown) {
// 使用服务端设置更新本地状态
// Update local state with server settings
const typedData = data as { settings: SettingsUpdate; lastSyncTime: string };
store.dispatch(replaceSettings({
settings: typedData.settings,
Expand All @@ -80,13 +80,13 @@ class SettingsOperationHandler implements OperationHandler {
}
}

// 创建Settings同步管理器实例
// Create Settings sync manager instance
export const settingsSyncManager = new GenericSyncManager(
'settings',
new SettingsAPIAdapter(),
new SettingsOperationHandler(),
10000 // 10秒同步间隔,设置同步频率较高
10000 // 10-second sync interval for frequent synchronization
)

// 为了保持向后兼容,提供一个包装方法
// Wrapper method to maintain backward compatibility
export const fetchSettingsFromServer = () => settingsSyncManager.fetchDataFromServer()
16 changes: 8 additions & 8 deletions src/app/componments/settings/settingsSyncManagerNew.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import {
replaceSettings
} from '../clock/ClockSlice'

// Settings API适配器
// Settings API adapter
class SettingsAPIAdapter implements SyncAPI {
async syncOperations(operations: SyncOperation[], lastSyncTime: string | null) {
// 转换为SettingsOperation类型
// Convert to SettingsOperation type
const settingsOperations: SettingsOperation[] = operations.map(op => ({
type: op.type,
payload: op.payload as SettingsPayload,
Expand All @@ -38,12 +38,12 @@ class SettingsAPIAdapter implements SyncAPI {
}
}

// Settings操作处理器
// Settings operation handler
class SettingsOperationHandler implements OperationHandler {
applyOperation(operation: SyncOperation) {
const { type, payload } = operation

// 类型断言,因为我们知道不同操作类型的payload结构
// Type assertion since we know payload structures for different operation types
const typedPayload = payload as { value: number | boolean | string };

switch (type) {
Expand Down Expand Up @@ -71,7 +71,7 @@ class SettingsOperationHandler implements OperationHandler {
}

replaceData(data: unknown) {
// 使用服务端设置更新本地状态
// Update local state with server settings
const typedData = data as { settings: SettingsUpdate; lastSyncTime: string };
store.dispatch(replaceSettings({
settings: typedData.settings,
Expand All @@ -80,13 +80,13 @@ class SettingsOperationHandler implements OperationHandler {
}
}

// 创建Settings同步管理器实例
// Create Settings sync manager instance
export const settingsSyncManager = new GenericSyncManager(
'settings',
new SettingsAPIAdapter(),
new SettingsOperationHandler(),
10000 // 10秒同步间隔,设置同步频率较高
10000 // 10-second sync interval for frequent synchronization
)

// 为了保持向后兼容,提供一个包装方法
// Wrapper method to maintain backward compatibility
export const fetchSettingsFromServer = () => settingsSyncManager.fetchDataFromServer()
18 changes: 9 additions & 9 deletions src/app/componments/todo/TodoTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ import {todoSyncActions} from "./todoSyncActions";
export interface RootProps {
}

// 过滤后的Todo项目接口,只包含符合过滤条件的subtodo
// Filtered Todo item interface that only includes subtodos matching the filter
export interface FilteredTodoItem extends Omit<TodoItem, 'subItems'> {
subItems: SubTodoItem[];
originalSubItems: SubTodoItem[]; // 保存原始的subItems用于编辑等操作
originalSubItems: SubTodoItem[]; // Preserve original subItems for editing and other operations
}

// 检查todo是否包含指定状态的subtodo
// Check whether a todo contains subtodos with the specified status
const hasSubtodosWithStatus = (todo: TodoItem, completed: boolean): boolean => {
if (!todo.subItems || todo.subItems.length === 0) {
return false;
}
return todo.subItems.some((subTodo: SubTodoItem) => subTodo.completed === completed && !subTodo.deleted);
};

// 根据filter过滤subtodo
// Filter subtodos according to the filter
const filterSubtodos = (subItems: SubTodoItem[], filter: VisibilityFilters): SubTodoItem[] => {
if (!subItems || subItems.length === 0) {
return [];
Expand All @@ -40,18 +40,18 @@ const filterSubtodos = (subItems: SubTodoItem[], filter: VisibilityFilters): Sub
}
};

// 检查todo是否应该根据filter显示
// Determine whether a todo should be displayed based on the filter
const shouldShowTodo = (todo: TodoItem, filter: VisibilityFilters): boolean => {
if (todo.deleted) return false;

switch (filter) {
case VisibilityFilters.SHOW_ALL:
return true;
case VisibilityFilters.SHOW_COMPLETED:
// 显示所有已完成的subtodo的todo,或者主todo已完成
// Show todos with all subtodos completed, or if the main todo is completed
return todo.completed || hasSubtodosWithStatus(todo, true);
case VisibilityFilters.SHOW_ACTIVE:
// 显示所有包含未完成subtodo的todo,或者主todo未完成
// Show todos containing unfinished subtodos, or if the main todo is incomplete
return !todo.completed || hasSubtodosWithStatus(todo, false);
default:
return true;
Expand All @@ -61,14 +61,14 @@ const shouldShowTodo = (todo: TodoItem, filter: VisibilityFilters): boolean => {
const getVisibleTodos = (todos: TodoItem[], filter: VisibilityFilters): FilteredTodoItem[] => {
const visibleTodos = todos.filter(todo => shouldShowTodo(todo, filter));

// 为每个可见的todo创建过滤后的版本
// Create a filtered version for each visible todo
const result = visibleTodos.map(todo => {
const filteredSubItems = filterSubtodos(todo.subItems, filter);
//console.log(`[getVisibleTodos] Todo "${todo.text}": original subtodos: ${todo.subItems.length}, filtered subtodos: ${filteredSubItems.length}`);
return {
...todo,
subItems: filteredSubItems,
originalSubItems: todo.subItems // 保存原始数据
originalSubItems: todo.subItems // Save original data
};
});

Expand Down
Loading