-
Notifications
You must be signed in to change notification settings - Fork 90
[WIP] feat: 添加计时器功能以跟踪阅读时间并提供显示选项 #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
WalkthroughA user timer feature was introduced, tracking elapsed time and storing it in a reactive store. The timer is started in the content view and its value is displayed in the layout's bottom bar when enabled. New settings allow toggling the time display. Supporting store properties and formatting logic were added, with minor updates to types. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ContentPage
participant TimerHook
participant SettingStore
participant Layout
participant SettingsPage
User->>ContentPage: Loads page
ContentPage->>TimerHook: Calls userTimer()
TimerHook->>SettingStore: Every second, increment readTime
User->>SettingsPage: Opens settings
SettingsPage->>SettingStore: Toggles timeIsShow
Layout->>SettingStore: Reads timeIsShow and readTime
Layout->>Layout: Formats and displays elapsed time if timeIsShow is true
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (1)
packages/web/src/pages/vscode/layout/index.vue (1)
43-43: Remove debug console.log statement.Debug logging should be removed from production code.
-console.log('settingStore.readTime:', settingStore.readTime);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
packages/web/src/pages/common/timer.ts(1 hunks)packages/web/src/pages/vscode/content/index.vue(2 hunks)packages/web/src/pages/vscode/layout/index.vue(2 hunks)packages/web/src/pages/vscode/settings/index.vue(2 hunks)packages/web/src/stores/setting.pc.ts(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/web/src/pages/common/timer.ts (1)
packages/web/src/stores/setting.pc.ts (1)
useSettingStore(45-92)
packages/web/src/stores/setting.pc.ts (1)
packages/web/src/utils/font.ts (1)
FontData(3-8)
🔇 Additional comments (2)
packages/web/src/stores/setting.pc.ts (1)
7-7: LGTM: Font property made optional.Making the
fontproperty optional inReadStyleis a reasonable change that provides more flexibility.packages/web/src/pages/vscode/layout/index.vue (1)
35-39: LGTM: Store import and usage.The store is properly imported and instantiated in the component setup.
| import { useSettingStore } from '@/stores/setting'; | ||
| /** 启动和销毁计时器 hooks */ | ||
| export const userTimer = () => { | ||
| const settingStore = useSettingStore(); | ||
|
|
||
| const timerId = ref(); | ||
|
|
||
| onMounted(() => { | ||
| timerId.value = setInterval(() => { | ||
| settingStore.readTime += 1; | ||
| }, 1000); | ||
| }); | ||
|
|
||
| onBeforeUnmount(() => { | ||
| if (timerId.value) { | ||
| clearInterval(timerId.value); | ||
| } | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix missing imports and consider timer behavior.
Several critical issues need to be addressed:
- Missing Vue imports - This will cause runtime errors:
- Timer runs continuously - Consider pausing when user is inactive
- Function naming -
userTimershould probably beuseTimer
Apply this diff to fix the missing imports:
+import { ref, onMounted, onBeforeUnmount } from 'vue';
import { useSettingStore } from '@/stores/setting';
-/** 启动和销毁计时器 hooks */
-export const userTimer = () => {
+
+/** 启动和销毁计时器 hook */
+export const useTimer = () => {
const settingStore = useSettingStore();
const timerId = ref();
onMounted(() => {
timerId.value = setInterval(() => {
settingStore.readTime += 1;
}, 1000);
});
onBeforeUnmount(() => {
if (timerId.value) {
clearInterval(timerId.value);
+ timerId.value = null;
}
});
};Consider adding pause/resume functionality for when the user is inactive:
export const useTimer = () => {
const settingStore = useSettingStore();
const timerId = ref<number | null>(null);
const isActive = ref(true);
const startTimer = () => {
if (timerId.value) return;
timerId.value = setInterval(() => {
if (isActive.value) {
settingStore.readTime += 1;
}
}, 1000);
};
const pauseTimer = () => {
isActive.value = false;
};
const resumeTimer = () => {
isActive.value = true;
};
// Add window focus/blur listeners
onMounted(() => {
startTimer();
window.addEventListener('focus', resumeTimer);
window.addEventListener('blur', pauseTimer);
});
onBeforeUnmount(() => {
if (timerId.value) {
clearInterval(timerId.value);
timerId.value = null;
}
window.removeEventListener('focus', resumeTimer);
window.removeEventListener('blur', pauseTimer);
});
};🤖 Prompt for AI Agents
In packages/web/src/pages/common/timer.ts lines 1 to 19, the code is missing
necessary Vue imports like ref, onMounted, and onBeforeUnmount, which causes
runtime errors. Rename the function from userTimer to useTimer for clarity.
Implement pause and resume functionality to stop the timer when the user is
inactive by tracking window focus and blur events, and ensure the timerId is
properly typed and cleared on unmount. Add event listeners for window focus and
blur in onMounted and remove them in onBeforeUnmount to manage timer activity
accordingly.
| import { ContentType } from '@any-reader/rule-utils'; | ||
| import { useContent, useTheme } from '@/pages/common/content'; | ||
| import { useReadStore } from '@/stores/read'; | ||
| import { userTimer } from '@/pages/common/timer'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update import name and add error handling.
The import should be updated to match the corrected function name from the timer module.
-import { userTimer } from '@/pages/common/timer';
+import { useTimer } from '@/pages/common/timer';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { userTimer } from '@/pages/common/timer'; | |
| -import { userTimer } from '@/pages/common/timer'; | |
| +import { useTimer } from '@/pages/common/timer'; |
🤖 Prompt for AI Agents
In packages/web/src/pages/vscode/content/index.vue at line 56, update the import
statement to use the corrected function name from the timer module instead of
'userTimer'. Also, add appropriate error handling around the usage of this
imported function to handle potential failures gracefully.
| useTheme(contentRef); | ||
| userTimer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update function call and consider error handling.
Update the function call to match the corrected name and consider adding error handling.
-userTimer();
+useTimer();Consider wrapping the timer initialization with error handling:
try {
useTimer();
} catch (error) {
console.warn('Failed to initialize reading timer:', error);
}🤖 Prompt for AI Agents
In packages/web/src/pages/vscode/content/index.vue at line 67, the function call
userTimer() should be updated to useTimer() to match the corrected function
name. Additionally, wrap the useTimer() call in a try-catch block to handle
potential errors gracefully by logging a warning message with the error details.
| <div v-if="!hideBtmBar" class="flex gap-4 px-8 py-4"> | ||
| <div v-if="!hideBtmBar" class="flex items-center gap-4 px-8 py-4"> | ||
| <div class="codicon codicon-arrow-left vsc-toolbar-btn" @click="router.back()"></div> | ||
| <div v-if="settingStore.timeIsShow">已摸鱼:{{ showTIme }}</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update template to use corrected computed property name.
Update the template binding to match the corrected computed property name.
- <div v-if="settingStore.timeIsShow">已摸鱼:{{ showTIme }}</div>
+ <div v-if="settingStore.timeIsShow">已摸鱼:{{ showTime }}</div>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div v-if="settingStore.timeIsShow">已摸鱼:{{ showTIme }}</div> | |
| <div v-if="settingStore.timeIsShow">已摸鱼:{{ showTime }}</div> |
🤖 Prompt for AI Agents
In packages/web/src/pages/vscode/layout/index.vue at line 13, the template uses
the computed property name "showTIme" which is incorrect. Update the template
binding to use the corrected computed property name exactly as defined in the
script, ensuring proper casing and spelling.
| const showTIme = computed(() => { | ||
| const readTime = settingStore.readTime; | ||
| if (readTime <= 0) return 0; | ||
| const hours = Math.floor(readTime / 3600); | ||
| const minutes = Math.floor((readTime % 3600) / 60); | ||
| const seconds = readTime % 60; | ||
| return `${hours}:${minutes}:${seconds}`; | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix typo in computed property name and improve formatting.
The computed property has a typo and the time formatting could be improved.
Apply this diff to fix the typo and improve formatting:
-const showTIme = computed(() => {
+const showTime = computed(() => {
const readTime = settingStore.readTime;
if (readTime <= 0) return 0;
const hours = Math.floor(readTime / 3600);
const minutes = Math.floor((readTime % 3600) / 60);
const seconds = readTime % 60;
- return `${hours}:${minutes}:${seconds}`;
+ return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const showTIme = computed(() => { | |
| const readTime = settingStore.readTime; | |
| if (readTime <= 0) return 0; | |
| const hours = Math.floor(readTime / 3600); | |
| const minutes = Math.floor((readTime % 3600) / 60); | |
| const seconds = readTime % 60; | |
| return `${hours}:${minutes}:${seconds}`; | |
| }); | |
| const showTime = computed(() => { | |
| const readTime = settingStore.readTime; | |
| if (readTime <= 0) return 0; | |
| const hours = Math.floor(readTime / 3600); | |
| const minutes = Math.floor((readTime % 3600) / 60); | |
| const seconds = readTime % 60; | |
| return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; | |
| }); |
🤖 Prompt for AI Agents
In packages/web/src/pages/vscode/layout/index.vue around lines 44 to 52, the
computed property name "showTIme" contains a typo and the time formatting lacks
leading zeros for minutes and seconds. Rename the property to "showTime" and
update the return statement to format hours, minutes, and seconds with leading
zeros (e.g., using padStart or equivalent) to ensure consistent time display.
| <SettingRow title="摸鱼时间"> | ||
| <vscode-checkbox :checked="settingStore.timeIsShow" @input="handleInput">显示/隐藏</vscode-checkbox> | ||
| </SettingRow> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix checkbox binding and event handling.
The current implementation has issues with the two-way binding:
- The event handler only logs but doesn't update the store state
- Missing proper two-way binding pattern
Apply this diff to fix the checkbox binding:
- <SettingRow title="摸鱼时间">
- <vscode-checkbox :checked="settingStore.timeIsShow" @input="handleInput">显示/隐藏</vscode-checkbox>
- </SettingRow>
+ <SettingRow title="摸鱼时间">
+ <vscode-checkbox
+ :checked="settingStore.timeIsShow"
+ @input="(event) => settingStore.timeIsShow = event.target.checked"
+ >
+ 显示/隐藏
+ </vscode-checkbox>
+ </SettingRow>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <SettingRow title="摸鱼时间"> | |
| <vscode-checkbox :checked="settingStore.timeIsShow" @input="handleInput">显示/隐藏</vscode-checkbox> | |
| </SettingRow> | |
| <SettingRow title="摸鱼时间"> | |
| <vscode-checkbox | |
| :checked="settingStore.timeIsShow" | |
| @input="(event) => settingStore.timeIsShow = event.target.checked" | |
| > | |
| 显示/隐藏 | |
| </vscode-checkbox> | |
| </SettingRow> |
🤖 Prompt for AI Agents
In packages/web/src/pages/vscode/settings/index.vue around lines 12 to 14, the
checkbox component uses a :checked prop and an @input event that only logs
without updating the store, breaking two-way binding. Replace :checked with
v-model bound to settingStore.timeIsShow and update the event handler to modify
the store state accordingly, ensuring proper two-way binding and reactive
updates.
| const handleInput = (event) => { | ||
| console.log('event:', event); | ||
| console.log('event.target.checked:', event.target.checked); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove unused event handler.
The handleInput function is no longer needed after fixing the checkbox binding.
-const handleInput = (event) => {
- console.log('event:', event);
- console.log('event.target.checked:', event.target.checked);
-};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const handleInput = (event) => { | |
| console.log('event:', event); | |
| console.log('event.target.checked:', event.target.checked); | |
| }; |
🤖 Prompt for AI Agents
In packages/web/src/pages/vscode/settings/index.vue around lines 36 to 39, the
handleInput function is no longer used after fixing the checkbox binding. Remove
the entire handleInput function to clean up unused code.
| const timeIsShow = ref<boolean>(true); | ||
| const readTime = ref<number>(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding timer state to persistent configuration.
The new timeIsShow and readTime variables are not included in the persistent data object that gets synchronized with the backend via readConfig/updateConfig. This means:
- Settings won't persist across application restarts
- Timer value will reset to 0 on page reload
- User preference for showing time won't be remembered
Consider moving these properties into the Setting type and data object:
export type Setting = {
readStyle: ReadStyle;
keyboardShortcuts: KeyboardShortcuts;
sidebar: Sidebar;
bookDir: string;
+ timeIsShow: boolean;
+ readTime: number;
};
export const useSettingStore = defineStore('setting', () => {
const data = reactive<Setting>({
readStyle: {
// ...existing properties
},
keyboardShortcuts: {
// ...existing properties
},
sidebar: 'left',
- bookDir: ''
+ bookDir: '',
+ timeIsShow: true,
+ readTime: 0
});
- /** 是否显示摸鱼时间 */
- const timeIsShow = ref<boolean>(true);
- const readTime = ref<number>(0);
return {
data,
- readTime,
- timeIsShow,
sync
};
});Then access them via settingStore.data.timeIsShow and settingStore.data.readTime in components.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const timeIsShow = ref<boolean>(true); | |
| const readTime = ref<number>(0); | |
| export type Setting = { | |
| readStyle: ReadStyle; | |
| keyboardShortcuts: KeyboardShortcuts; | |
| sidebar: Sidebar; | |
| bookDir: string; | |
| timeIsShow: boolean; | |
| readTime: number; | |
| }; | |
| export const useSettingStore = defineStore('setting', () => { | |
| const data = reactive<Setting>({ | |
| readStyle: { | |
| // ...existing properties | |
| }, | |
| keyboardShortcuts: { | |
| // ...existing properties | |
| }, | |
| sidebar: 'left', | |
| bookDir: '', | |
| timeIsShow: true, | |
| readTime: 0 | |
| }); | |
| // ...other store logic (e.g. readConfig, updateConfig, etc.)... | |
| return { | |
| data, | |
| sync | |
| }; | |
| }); |
🤖 Prompt for AI Agents
In packages/web/src/stores/setting.pc.ts around lines 69 to 70, the new reactive
variables timeIsShow and readTime are not part of the persistent data object
synchronized with the backend, causing their values and user preferences to
reset on reload. To fix this, add timeIsShow and readTime to the Setting type
and include them in the data object that is read and updated via readConfig and
updateConfig. Then update all references to these variables to access them
through settingStore.data.timeIsShow and settingStore.data.readTime to ensure
persistence across restarts.
老哥,想加个计时器功能你看看咋样?
我在
packages/web/src/stores/setting.pc.ts文件里加了两个变量,但在 vue 文件中读取的时候都是undefined是为什么?Summary by CodeRabbit
New Features
Improvements