Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit dfbc211

Browse files
authored
feat: no server mode (#73, #minor)
* offline mode 를 위해 dexie 추가 서버측 로직을 db.ts에 stats 제외하고 추가 * stats 제외하고 indexed db 바라보도록 교체 * 카테고리 관련 로직 놓친거 추가 * 인덱싱 필드 최소화 * off 리스너 해제 원활하지 않아 아예 제거 * stats 계산도 indexed db 통해서 * 더이상 local cache 전략 제거 * 툴팁에선 분 표시시 소수점 단위 표시되지 않도록 * ui 타이틀 수정 * 불필요한 패키지 삭제 * 기록 ux 변경
1 parent 4aa8f88 commit dfbc211

File tree

23 files changed

+371
-118
lines changed

23 files changed

+371
-118
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,12 @@
7070
"@radix-ui/react-toggle-group": "^1.1.0",
7171
"@radix-ui/react-tooltip": "^1.1.2",
7272
"@rive-app/react-canvas": "^4.13.3",
73-
"@tanstack/query-sync-storage-persister": "^5.51.9",
7473
"@tanstack/react-query": "^5.51.4",
7574
"@tanstack/react-query-devtools": "^5.51.4",
76-
"@tanstack/react-query-persist-client": "^5.51.9",
7775
"class-variance-authority": "^0.7.0",
7876
"clsx": "^2.1.1",
7977
"date-fns": "^4.1.0",
78+
"dexie": "^4.2.0",
8079
"electron-squirrel-startup": "^1.0.1",
8180
"embla-carousel-autoplay": "^8.2.0",
8281
"embla-carousel-react": "^8.1.6",

src/preload/preload.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ const electronAPI: IElectronAPI = {
2323
endPomodoro: (reason) => ipcRenderer.invoke('end-pomodoro', reason),
2424

2525
onTickPomodoro: (callback) => ipcRenderer.on('tick-pomodoro', callback),
26-
offTickPomodoro: (callback) => ipcRenderer.off('tick-pomodoro', callback),
26+
offTickPomodoro: () => ipcRenderer.removeAllListeners('tick-pomodoro'),
2727

2828
onEndPomodoro: (callback) => ipcRenderer.on('end-pomodoro', callback),
29-
offEndPomodoro: (callback) => ipcRenderer.off('end-pomodoro', callback),
29+
offEndPomodoro: () => ipcRenderer.removeAllListeners('end-pomodoro'),
3030

3131
onOnceExceedGoalTime: (callback) => ipcRenderer.on('once-exceed-goal-time', callback),
32-
offOnceExceedGoalTime: (callback) => ipcRenderer.off('once-exceed-goal-time', callback),
32+
offOnceExceedGoalTime: () => ipcRenderer.removeAllListeners('once-exceed-goal-time'),
3333
};
3434

3535
contextBridge.exposeInMainWorld('electronAPI', electronAPI);

src/renderer/app/provider.tsx

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,24 @@
11
import { PropsWithChildren } from 'react';
22

3-
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister';
4-
import { QueryClient } from '@tanstack/react-query';
3+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
54
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
6-
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
75

86
import { Toaster } from '@/shared/ui';
97

108
const queryClient = new QueryClient({
119
defaultOptions: {
1210
queries: {
13-
// 디바이스와 서버간 데이터는 달라질 일이 거의 없을거라고 가정하여, 캐시를 무제한으로 설정
14-
gcTime: Infinity,
15-
staleTime: Infinity,
1611
retry: 0,
1712
},
1813
},
1914
});
2015

21-
const persister = createSyncStoragePersister({
22-
storage: window.localStorage,
23-
});
24-
2516
export const Provider = ({ children }: PropsWithChildren) => {
2617
return (
27-
<PersistQueryClientProvider
28-
client={queryClient}
29-
persistOptions={{ persister }}
30-
onSuccess={async () => {
31-
await queryClient.resumePausedMutations();
32-
}}
33-
>
18+
<QueryClientProvider client={queryClient}>
3419
{children}
3520
<Toaster />
3621
<ReactQueryDevtools buttonPosition="bottom-right" initialIsOpen={false} />
37-
</PersistQueryClientProvider>
22+
</QueryClientProvider>
3823
);
3924
};

src/renderer/entities/stats/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Category } from '../category';
22

33
export type Stats = {
4-
data: string;
4+
date: string;
55
totalFocusTime: string;
66
focusTimes: Array<{
77
no: number;

src/renderer/features/cat/hooks/use-cats.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@ import { useQuery } from '@tanstack/react-query';
22

33
import { Cat } from '@/entities/cat';
44
import { QUERY_KEY } from '@/shared/constants';
5-
import { useAuthClient } from '@/shared/hooks';
5+
import * as db from '@/shared/utils/db';
66

77
export const useCats = () => {
8-
const authClient = useAuthClient();
9-
return useQuery({
8+
return useQuery<Cat[]>({
109
queryKey: QUERY_KEY.CATS,
1110
queryFn: async () => {
12-
return await authClient?.get<Cat[]>('/api/v1/cats');
11+
return await db.getCats();
1312
},
14-
enabled: !!authClient,
1513
});
1614
};

src/renderer/features/cat/hooks/use-rename-selected-cat.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
33
import { Cat } from '@/entities/cat';
44
import { User } from '@/entities/user';
55
import { MUTATION_KEY, QUERY_KEY } from '@/shared/constants';
6-
import { useAuthClient } from '@/shared/hooks';
6+
import * as db from '@/shared/utils/db';
77

88
export const useRenameSelectedCat = () => {
99
const queryClient = useQueryClient();
10-
const authClient = useAuthClient();
1110

1211
return useMutation({
1312
mutationKey: MUTATION_KEY.RENAME_SELECTED_CAT,
1413
mutationFn: async (catName: Cat['name']) => {
15-
return await authClient?.put('/api/v1/cats', { name: catName });
14+
return await db.renameCat(catName);
1615
},
1716
onMutate: (catName) => {
1817
// cancel current queries

src/renderer/features/cat/hooks/use-select-cat.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
33
import { Cat } from '@/entities/cat';
44
import { User } from '@/entities/user';
55
import { MUTATION_KEY, QUERY_KEY } from '@/shared/constants';
6-
import { useAuthClient } from '@/shared/hooks';
6+
import * as db from '@/shared/utils/db';
77

88
export const useSelectCat = () => {
99
const queryClient = useQueryClient();
10-
const authClient = useAuthClient();
1110

1211
return useMutation({
1312
mutationKey: MUTATION_KEY.SELECT_CAT,
1413
mutationFn: async (catNo: Cat['no']) => {
15-
return await authClient?.put<unknown>('/api/v1/users/cats', { catNo });
14+
return await db.selectCat(catNo);
1615
},
1716
onMutate: (catNo) => {
1817
// cancel current queries

src/renderer/features/category/hooks/use-categories.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import { useQuery } from '@tanstack/react-query';
22

3-
import { Category } from '@/entities/category';
43
import { QUERY_KEY } from '@/shared/constants';
5-
import { useAuthClient } from '@/shared/hooks';
4+
import * as db from '@/shared/utils/db';
65

76
export const useCategories = () => {
8-
const authClient = useAuthClient();
97
const query = useQuery({
108
queryKey: QUERY_KEY.CATEGORIES,
119
queryFn: async () => {
12-
return await authClient?.get<Category[]>('/api/v1/categories');
10+
return await db.getCategories();
1311
},
14-
enabled: !!authClient,
1512
});
1613
const sortedData = query.data?.sort((a, b) => a.position - b.position);
1714
const currentCategory = query.data?.find((category) => category.isSelected) ?? sortedData?.[0];

src/renderer/features/category/hooks/use-category.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import { useQuery } from '@tanstack/react-query';
22

33
import { Category } from '@/entities/category';
44
import { QUERY_KEY } from '@/shared/constants';
5-
import { useAuthClient } from '@/shared/hooks';
5+
import * as db from '@/shared/utils/db';
66

77
export const useCategory = (no?: number) => {
8-
const authClient = useAuthClient();
9-
return useQuery({
8+
return useQuery<Category>({
109
queryKey: [...QUERY_KEY.CATEGORIES, no],
1110
queryFn: async () => {
12-
return await authClient?.get<Category>(`/api/v1/categories/${no}`);
11+
return await db.getCategory(no!);
1312
},
14-
enabled: !!authClient && no != null,
13+
enabled: no != null,
1514
});
1615
};

src/renderer/features/category/hooks/use-create-category.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
22

33
import { Category, CategoryIconType } from '@/entities/category';
44
import { MUTATION_KEY, QUERY_KEY } from '@/shared/constants';
5-
import { useAuthClient } from '@/shared/hooks';
5+
import * as db from '@/shared/utils/db';
66

77
type CreateCategoryBody = {
88
title: string;
@@ -14,11 +14,10 @@ type CreateCategoryParams = {
1414

1515
export const useCreateCategory = () => {
1616
const queryClient = useQueryClient();
17-
const authClient = useAuthClient();
1817
return useMutation({
1918
mutationKey: MUTATION_KEY.CREATE_CATEGORY,
2019
mutationFn: async ({ body }: CreateCategoryParams) => {
21-
return await authClient?.post<unknown, CreateCategoryBody>('/api/v1/categories', body);
20+
return await db.createCategory(body);
2221
},
2322
onMutate: ({ body }) => {
2423
queryClient.cancelQueries({ queryKey: QUERY_KEY.CATEGORIES });

0 commit comments

Comments
 (0)