Conversation
WalkthroughThis PR introduces scheduled task starting (new "Scheduled" status, engine scheduler logic, backend commands, store/API wiring, ScheduleDialog/MissedScheduleDialog UI), replaces task move-up/down with drag-and-drop/keyboard reordering, adds a signed updater manifest build pipeline in the release workflow, enables HTTP/2 ALPN in the HTTP client, adjusts engine HTTP header/cookie/filename handling, and updates official website URLs plus minor fixes. ChangesScheduled Task Feature
Updater manifest and release signing
HTTP client HTTP/2 support
Engine HTTP download improvements
Misc fixes and URL updates
Estimated code review effort: 4 (Complex) | ~75 minutes Possibly related PRs
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
src-tauri/risuko-engine/src/engine/http.rs (1)
963-979: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
cf_clearancefromload-cookiesstill reaches this probe
headers_have_cookie_name(&headers, "cf_clearance")only inspects the explicitCookieheader. Cookies loaded into the shared jar are injected later, so a jar-suppliedcf_clearancestill lets the range probe run. Check the jar here too, or ensure this guard only relies on header-based cookies.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/risuko-engine/src/engine/http.rs` around lines 963 - 979, The range-probe guard in the HTTP flow still only checks the explicit Cookie header via headers_have_cookie_name, so a jar-injected cf_clearance can slip through and trigger probe_range_support anyway. Update the probe gating logic around wants_range_probe in http.rs to also consult the shared cookie jar (or otherwise make the guard consistently header-only), and keep the cf_clearance skip decision aligned with the actual cookie source before calling probe_range_support..github/workflows/release.yml (1)
270-303: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winKeep a plain Linux AppImage asset for tagged releases
.github/workflows/release.yml:270-303publishesRisuko_<version>_linux_<arch>.AppImage.tar.gzfor tagged Linux builds, butpackages/risuko-app/bin.jsstill downloadsRisuko_<version>_linux_<arch>.AppImage. That makes tagged-release Linux installs fail on first download. Keep the updater.tar.gz+.sigpair, and also upload the plain.AppImageas a separate asset.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/release.yml around lines 270 - 303, The tagged Linux release path in release.yml only copies the updater artifact from the bundle, so packages/risuko-app/bin.js cannot fetch the plain Risuko_<version>_linux_<arch>.AppImage it expects. Update the release asset handling in the tagged-release branch to keep publishing the updater .tar.gz and .sig pair, and also add a separate upload/copy step for the plain .AppImage using the existing appimage lookup logic so both artifact shapes are available.src-tauri/risuko-engine/src/engine/task.rs (1)
17-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd
Scheduledtostatus_as_strunit test.
TaskStatus::as_str()gains a mapping forTaskStatus::Scheduledto the"scheduled"string. The mapping itself is correct, but the existingstatus_as_strtest (further down in the file) doesn't cover the newScheduledvariant, leaving this mapping without direct regression coverage.♻️ Proposed test addition
assert_eq!(TaskStatus::Waiting.as_str(), "waiting"); assert_eq!(TaskStatus::Paused.as_str(), "paused"); + assert_eq!(TaskStatus::Scheduled.as_str(), "scheduled"); assert_eq!(TaskStatus::Complete.as_str(), "complete");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/risuko-engine/src/engine/task.rs` around lines 17 - 33, The TaskStatus::as_str mapping for TaskStatus::Scheduled is correct, but the status_as_str unit test does not cover it. Update the status_as_str test in task.rs to include a case for TaskStatus::Scheduled returning "scheduled", alongside the existing TaskStatus variants so the new mapping is directly covered.src/renderer/store/task.ts (1)
407-470: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFetch
scheduledindependently
get_global_statonly providesnumActive,numWaiting, andnumStoppedTotal, soscheduledCountcan’t be derived here. As written, scheduled-only states collapse to0, and thenumWaiting > 0gate also skips scheduled tasks whenever waiting is empty.Fetch
scheduledseparately before deriving the sidebar counts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderer/store/task.ts` around lines 407 - 470, The sidebar count logic in updateTaskCountsFromStat incorrectly derives scheduled tasks from the waiting branch, so scheduled-only items can be missed or set to 0. Update the fetch flow in updateTaskCountsFromStat to request the scheduled list independently via api.fetchTaskList("scheduled") whenever counts are being refreshed, instead of tying it to numWaiting. Then compute scheduledCount from that separate result and keep the existing active, waiting, stopped, and completed handling intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Around line 557-563: The release workflow step for uploading latest.json
should avoid the redundant third-party action and use the preinstalled gh CLI
instead. Update the upload step in the release job to perform the same GitHub
Release file upload directly with gh release upload, keeping the existing
tag_name/latest.json behavior intact. Use the existing release upload step as
the place to make this change and preserve the surrounding workflow logic.
In `@scripts/build-updater-manifest.mjs`:
- Around line 13-24: The platforms accumulator in build-updater-manifest.mjs
should not be a plain object because fragment keys like "__proto__" can collide
with Object.prototype and break the duplicate check or output. Change the
platforms initialization to a null-prototype object (or a Map) and keep the
existing frag.key validation and duplicate detection in the same loop so keys
are treated as ordinary entries rather than inherited properties.
In `@src-tauri/risuko-engine/src/engine/manager.rs`:
- Around line 2694-2731: `move_tasks` currently defaults to appending moved
items when `target_gid` is missing, which hides stale target state. Update
`move_tasks` in `manager.rs` to validate that `target_gid` exists in the
remaining task list before computing `insert_at`, and return an error instead of
falling back to `remaining.len()` if it is absent. Keep the existing
`move_set`/`moved` handling and ensure `reorder_tasks` callers in
`engine_cmds.rs` will surface the missing-target failure rather than silently
reordering to the end.
In `@src/renderer/components/Native/EngineClient.vue`:
- Around line 1048-1065: The checkMissedSchedules method currently reads only
the first scheduled-task page from fetchScheduledTaskList, so missed schedules
beyond the 5,000-item default are skipped. Update the checkMissedSchedules flow
to request only gid and scheduleMissed via keys: ["gid", "scheduleMissed"], then
loop through results using offset and num until no more tasks are returned,
aggregating missed entries before calling useAppStore().showMissedScheduled.
In `@src/renderer/components/Task/AddTask.vue`:
- Around line 207-215: The schedule field visibility in AddTask.vue is tied too
strictly to the dialog type, which breaks mixed queues where torrent, metalink,
and URI items coexist. Update the visibility logic around the DateTimePicker to
use a computed helper based on the actual queue contents and existing symbols
like queue, type, uriDraft, and ADD_TASK_TYPE.TORRENT instead of the hardcoded
'torrent' check. Also consider adding a user-facing hint when startAt is set but
some queued torrent items will ignore it so the dropped schedule is not silent.
In `@src/renderer/components/Task/ScheduleDialog.vue`:
- Around line 74-93: The schedule dialog still allows past times to be selected
and confirmed because `nextTwoAm()` is only used as a fallback and the current
`visible` watcher in `ScheduleDialog.vue` reuses `task.startAt` even when it has
already elapsed. Update the `visible` watcher to prefill `startAt` only when
`this.task?.startAt` is a valid future timestamp, otherwise fall back to
`nextTwoAm()`, and tighten the `confirm` disabled check so it only enables when
`startAt` is greater than `Date.now() / 1000`. Use the `nextTwoAm`, `visible`
watcher, and `confirm` logic in `ScheduleDialog.vue` as the main touchpoints.
In `@src/renderer/components/Task/TaskItem.vue`:
- Around line 10-24: The drag handle in TaskItem.vue has an ARIA/keyboard
mismatch: the element with role="button" in TaskItem and the related reorder
handle at the other referenced location should either support Enter/Space
activation or use a more appropriate draggable/slider-style role for the
Arrow-key-only interaction. Update onHandleKeydown and the handle markup so
keyboard users have a consistent activation model, and add a live-region
announcement after keyboard reorders to report the new position.
In `@src/renderer/components/Task/TaskList.vue`:
- Around line 11-23: The TaskList drag/drop marker currently uses a bare attr
attribute and the drag-move path repeatedly queries the DOM, so update the row
marker in TaskList.vue and any related lookup logic (such as closest("[attr]")
and getAttribute("attr")) to use a clearer data-task-key data attribute instead.
Also reduce work in onDragMove by caching the .task-list scroller (and any
needed measurements) when drag starts in onHandleDown, then reuse that cached
element during pointermove instead of re-querying and recomputing on every
event.
- Around line 265-285: The drag start logic in onHandleDown is leaking window
listeners when a new drag begins before the previous one ends. Before assigning
new bound handlers and calling window.addEventListener, clear any existing drag
state by invoking the existing cleanup path (for example clearDragState) or
explicitly removing the current _onDragMove/_onDragUp/_onDragCancel listeners
first. Keep the fix centered on onHandleDown and the shared drag-state cleanup
so repeated handle-down events cannot leave stale listeners attached.
In `@src/renderer/components/ui/date-time-picker/DateTimePicker.vue`:
- Around line 203-209: The month navigation buttons in DateTimePicker.vue are
icon-only and need accessible names. Update the prevMonth and nextMonth Button
elements in DateTimePicker to include clear aria-labels such as “Previous month”
and “Next month” (or equivalent visible text) so screen readers can announce
them, keeping the existing ChevronLeft/ChevronRight icons unchanged.
In `@src/shared/locales/zh-CN/task.ts`:
- Around line 5-22: The zh-CN task locale is missing new keys that exist in the
en-US task translations, so add the absent entries to the task locale object in
task.ts: start-now-fail, schedule-fail, missed-schedule-start-all-fail, and
reorder-handle. Make sure the wording matches the existing zh-CN style, and
include reorder-handle so TaskItem.vue can use a localized aria-label instead of
falling back to English.
In `@src/shared/locales/zh-TW/task.ts`:
- Around line 5-22: Add the missing zh-TW task locale entries that exist in
en-US and zh-CN: `start-now-fail`, `schedule-fail`,
`missed-schedule-start-all-fail`, and `reorder-handle`. Update the `task` locale
object in `src/shared/locales/zh-TW/task.ts` alongside the existing keys so the
drag-handle `aria-label` and schedule/start-now failure messages are translated
for zh-TW users.
---
Outside diff comments:
In @.github/workflows/release.yml:
- Around line 270-303: The tagged Linux release path in release.yml only copies
the updater artifact from the bundle, so packages/risuko-app/bin.js cannot fetch
the plain Risuko_<version>_linux_<arch>.AppImage it expects. Update the release
asset handling in the tagged-release branch to keep publishing the updater
.tar.gz and .sig pair, and also add a separate upload/copy step for the plain
.AppImage using the existing appimage lookup logic so both artifact shapes are
available.
In `@src-tauri/risuko-engine/src/engine/http.rs`:
- Around line 963-979: The range-probe guard in the HTTP flow still only checks
the explicit Cookie header via headers_have_cookie_name, so a jar-injected
cf_clearance can slip through and trigger probe_range_support anyway. Update the
probe gating logic around wants_range_probe in http.rs to also consult the
shared cookie jar (or otherwise make the guard consistently header-only), and
keep the cf_clearance skip decision aligned with the actual cookie source before
calling probe_range_support.
In `@src-tauri/risuko-engine/src/engine/task.rs`:
- Around line 17-33: The TaskStatus::as_str mapping for TaskStatus::Scheduled is
correct, but the status_as_str unit test does not cover it. Update the
status_as_str test in task.rs to include a case for TaskStatus::Scheduled
returning "scheduled", alongside the existing TaskStatus variants so the new
mapping is directly covered.
In `@src/renderer/store/task.ts`:
- Around line 407-470: The sidebar count logic in updateTaskCountsFromStat
incorrectly derives scheduled tasks from the waiting branch, so scheduled-only
items can be missed or set to 0. Update the fetch flow in
updateTaskCountsFromStat to request the scheduled list independently via
api.fetchTaskList("scheduled") whenever counts are being refreshed, instead of
tying it to numWaiting. Then compute scheduledCount from that separate result
and keep the existing active, waiting, stopped, and completed handling intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 05801094-e072-4577-be31-d6faa2d14580
📒 Files selected for processing (47)
.github/workflows/release.ymlREADME-CN.mdREADME.mdscripts/build-updater-manifest.mjsscripts/build-updater-manifest.test.mjssrc-tauri/risuko-engine/src/engine/http.rssrc-tauri/risuko-engine/src/engine/manager.rssrc-tauri/risuko-engine/src/engine/task.rssrc-tauri/risuko-http/Cargo.tomlsrc-tauri/risuko-http/src/client.rssrc-tauri/risuko-http/src/connector.rssrc-tauri/src/commands/engine_cmds.rssrc-tauri/src/lib.rssrc-tauri/src/managers/clip_prompt.rssrc-tauri/src/managers/menu.rssrc/renderer/api/Api.tssrc/renderer/components/About/Copyright.vuesrc/renderer/components/Main.vuesrc/renderer/components/Native/EngineClient.vuesrc/renderer/components/Sidebar/Index.vuesrc/renderer/components/Task/AddTask.vuesrc/renderer/components/Task/CloudflareDialog.vuesrc/renderer/components/Task/Index.vuesrc/renderer/components/Task/MissedScheduleDialog.vuesrc/renderer/components/Task/ScheduleDialog.vuesrc/renderer/components/Task/TaskActions.vuesrc/renderer/components/Task/TaskItem.vuesrc/renderer/components/Task/TaskItemActions.vuesrc/renderer/components/Task/TaskList.vuesrc/renderer/components/Task/TaskStatus.vuesrc/renderer/components/TaskDetail/TaskGeneral.vuesrc/renderer/components/ui/date-time-picker/DateTimePicker.vuesrc/renderer/components/ui/date-time-picker/index.tssrc/renderer/pages/index/commands.tssrc/renderer/pages/index/main.tssrc/renderer/store/app.tssrc/renderer/store/batchQueue.tssrc/renderer/store/task.tssrc/renderer/styles/components/task.csssrc/renderer/utils/task.tssrc/shared/constants.tssrc/shared/locales/en-US/task.tssrc/shared/locales/zh-CN/task.tssrc/shared/locales/zh-TW/task.tssrc/shared/syncCategories.tssrc/shared/types/task.tssrc/shared/utils/index.ts
💤 Files with no reviewable changes (3)
- src/renderer/pages/index/commands.ts
- src/renderer/pages/index/main.ts
- src/renderer/components/Task/TaskActions.vue
There was a problem hiding this comment.
10 issues found across 47 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
5 issues found across 20 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Summary by cubic
Adds per-task scheduled starts, drag-and-drop queue reordering, and a preemptive queue cap so downloads start on time and the queue stays easy to manage. Improves HTTP compatibility with HTTP/2 and per-task User-Agent overrides, fixes Cloudflare retries and DateTimePicker issues, and adds CI updater manifest generation.
New Features
Bug Fixes
Written for commit b7c9dec. Summary will update on new commits.