Skip to content

Icons/set ascii as default - #3

Merged
romaintb merged 4 commits into
mainfrom
icons/set_ascii_as_default
Aug 18, 2025
Merged

Icons/set ascii as default#3
romaintb merged 4 commits into
mainfrom
icons/set_ascii_as_default

Conversation

@romaintb

@romaintb romaintb commented Aug 18, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Style

    • Default icon theme changed to ASCII for broader terminal compatibility.
    • Removed "Labels" and "Projects" section headers and tightened icon spacing for a cleaner sidebar list.
  • New Features

    • Project list now shows tree-aware indentation and truncates long names with ellipses.
    • Icons now support Emoji, Unicode and ASCII theme variations.

@romaintb romaintb self-assigned this Aug 18, 2025
@romaintb romaintb added the enhancement New feature or request label Aug 18, 2025
@coderabbitai

coderabbitai Bot commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Changed default icon theme to Ascii and added must_use annotations and multi-theme icon mappings in icons; adjusted projects list UI spacing, indentation and truncation; small refactors and option/map style updates across storage, sync, todoist, UI app, and dialog rendering conversions.

Changes

Cohort / File(s) Summary of changes
Icons & theme mappings
src/icons.rs
Default IconTheme now Ascii (was Unicode); IconService::new reformatted; many public methods annotated with #[must_use]; icons for project_regular, project_favorite, and label now provide values for Emoji, Unicode, and Ascii; tests updated for default and per-theme icons.
Projects list UI
src/ui/components/projects_list.rs
Removed/commented header ListItems for "Labels" and "Projects"; trimmed extra spaces around icon strings; added tree-depth-aware indentation, name truncation to fit width, helper functions for parent/root id lookup, and refactored item collection to map/collect.
Dialogs (height conversions)
src/ui/components/dialogs/project_creation_dialog.rs, src/ui/components/dialogs/task_creation_dialog.rs
Replaced as f32 casts with f32::from(...) for height/scale calculations; no behavioral changes.
Storage & task conversion
src/storage.rs
Replaced map(...).unwrap_or(false) with is_some_and(...) when deriving is_recurring; loop iteration changed from .iter() to &projects for insertion (semantics unchanged).
Sync optional ID mapping
src/sync.rs
Replaced closures that call to_string() with the function item std::string::ToString::to_string for mapping optional IDs (semantics unchanged).
Todoist task display recurring check
src/todoist.rs
Used is_some_and(...) to derive is_recurring from optional due instead of map(...).unwrap_or(false).
UI app result pattern matching
src/ui/app.rs
Changed match patterns from Ok(_) to Ok(()) for several async call results (create_project, delete_project, create_task); behavior unchanged.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch icons/set_ascii_as_default

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
src/icons.rs (1)

277-280: Update test_default_theme to expect the new Ascii default

The IconService::default() implementation now uses IconTheme::Ascii, so the existing test in src/icons.rs will fail. Please update the assertion accordingly:

• File: src/icons.rs

#[test]
fn test_default_theme() {
    let service = IconService::default();
-   assert_eq!(service.theme(), IconTheme::Unicode);
+   assert_eq!(service.theme(), IconTheme::Ascii);
}

No other tests reference Unicode as the default theme.

🧹 Nitpick comments (3)
src/ui/components/projects_list.rs (3)

27-33: Remove commented-out “Labels” header code

Leaving commented-out code adds noise. Prefer deleting it (version control preserves history).

Apply this diff:

-            // all_items.push(ListItem::new(Line::from(vec![Span::styled(
-            //     format!("{} Labels", app.icons.label()),
-            //     Style::default()
-            //         .fg(Color::Cyan)
-            //         .add_modifier(Modifier::BOLD),
-            // )])));

108-115: Remove commented-out “Projects” header code

Same rationale as the labels header: delete rather than comment out.

Apply this diff:

-        // all_items.push(ListItem::new(Line::from(vec![Span::styled(
-        //     format!("{} Projects", app.icons.projects_title()),
-        //     Style::default()
-        //         .fg(Color::Cyan)
-        //         .add_modifier(Modifier::BOLD),
-        // )])));

46-50: Optional: account for icon+space when truncating names

Now that we add a space after the icon, consider reducing the available width by 1 when truncating names so lines don’t slightly overflow on tight layouts. This applies to both labels and projects (projects already subtract indent; subtract one more for the icon’s trailing space).

Also applies to: 140-145

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 594d797 and 7530ded.

📒 Files selected for processing (2)
  • src/icons.rs (2 hunks)
  • src/ui/components/projects_list.rs (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/ui/components/projects_list.rs (1)
src/icons.rs (2)
  • icons (102-108)
  • label (263-269)
🔇 Additional comments (2)
src/icons.rs (2)

21-21: Default IconTheme switched to ASCII — LGTM

Change aligns with the PR objective to prefer ASCII for maximum compatibility. No API breakage.


88-88: Constructor formatting simplification — LGTM

Purely stylistic; no behavioral change.

Comment thread src/ui/components/projects_list.rs Outdated
Comment thread src/ui/components/projects_list.rs Outdated
@romaintb
romaintb merged commit 3b50d84 into main Aug 18, 2025
3 of 5 checks passed
@romaintb
romaintb deleted the icons/set_ascii_as_default branch August 18, 2025 17:05

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (2)
src/ui/components/projects_list.rs (2)

46-49: UTF-8 unsafe truncation can panic; use char-based truncation

Using String::len() and a byte slice like &s[..n] can split a multibyte character and panic at runtime. Switch to char-based truncation to be safe. (Optional: use display width-aware truncation; see note below.)

Apply this diff:

-                let display_name = if label.name.len() > max_name_width as usize {
-                    format!("{}…", &label.name[..max_name_width.saturating_sub(1) as usize])
-                } else {
-                    label.name.clone()
-                };
+                let max = max_name_width.saturating_sub(1) as usize; // reserve 1 for ellipsis
+                let display_name = if label.name.chars().count() > max {
+                    let truncated: String = label.name.chars().take(max).collect();
+                    format!("{}…", truncated)
+                } else {
+                    label.name.clone()
+                };

Optional improvement (display width-aware truncation for emoji/unicode): use unicode-width and unicode-segmentation to truncate by terminal cell width instead of char count. I can provide a helper if you want to go this route.


139-145: UTF-8 unsafe truncation (possible panic) and width doesn’t account for icon + space

  • Slicing by bytes can panic on multibyte chars.
  • available_width ignores the icon and a separating space, so names may overflow.

Make truncation char-safe and reserve room for the icon and a space.

Apply this diff:

-                // Truncate project name to fit sidebar (accounting for indentation)
-                let available_width = max_name_width.saturating_sub(indent.len() as u16);
-                let display_name = if project.name.len() > available_width as usize {
-                    format!("{}…", &project.name[..available_width.saturating_sub(1) as usize])
-                } else {
-                    project.name.clone()
-                };
+                // Truncate project name to fit sidebar (accounting for indentation + icon + space)
+                let available_width = max_name_width
+                    .saturating_sub(indent.len() as u16)
+                    .saturating_sub(2); // 1 for icon (ASCII default) + 1 for separating space
+                let avail = available_width.saturating_sub(1) as usize; // reserve 1 for ellipsis
+                let display_name = if project.name.chars().count() > avail {
+                    let truncated: String = project.name.chars().take(avail).collect();
+                    format!("{}…", truncated)
+                } else {
+                    project.name.clone()
+                };

Optional upgrade: compute the actual icon display width and truncate by unicode display width (unicode-width) to support Emoji/Unicode themes perfectly. Happy to wire that up if you want.

♻️ Duplicate comments (2)
src/ui/components/projects_list.rs (2)

53-55: Icon and label text are concatenated (“@inbox”) — insert a space after the icon

This was previously flagged and is still present. Add a single trailing space to the icon for readability.

Apply this diff:

-                    Span::styled(app.icons.label().to_string(), style),
+                    Span::styled(format!("{} ", app.icons.label()), style),

149-151: Icon and project name are concatenated (“#Project”) — add a space after the icon

Ensure there’s one separator for readability.

Apply this diff:

-                    Span::styled(icon.to_string(), style),
+                    Span::styled(format!("{} ", icon), style),
🧹 Nitpick comments (8)
src/sync.rs (1)

106-106: Stylistic nit: map(ToString::to_string) is fine; consider map(str::to_owned) or map(String::from)

Functionally equivalent, just a touch more idiomatic/readable in many codebases:

  • parent_id: parent_id.map(str::to_owned)
  • project_id: project_id.map(str::to_owned)

Also applies to: 122-122

src/ui/components/dialogs/project_creation_dialog.rs (1)

33-41: Theme consistency: avoid hardcoded emoji in dialog title

With ASCII as default, consider replacing the hardcoded "📁 New Project" title with the theme-aware icon service (e.g., app.icons.projects_title()), so the dialog title reflects the selected theme.

Outside the selected lines, update the title like:

.title(format!("{} New Project", app.icons.projects_title()))
src/icons.rs (3)

87-90: #[must_use] on constructors/getters: acceptable; watch for warning noise

  • Marking new, theme, icons, and convenience getters as #[must_use] is defensible to catch ignored-return mistakes.
  • Minor caution: this can surface warnings if any call sites intentionally ignore a value (rare for pure getters).

Optional micro-optimization: since IconSet holds only &'static strs, you could cache per-theme IconSet as const/static and return a &'static IconSet to avoid reconstructing on each call (not critical given the small size).

Also applies to: 93-96, 104-111, 213-256


260-266: New theme-aware project/label icons: add tests to lock behavior

Good addition. Consider adding unit tests that assert project_regular(), project_favorite(), and label() values for Emoji/Unicode/Ascii, similar to the existing task_status tests, to prevent regressions.

If you want, I can draft the test cases mirroring the existing style.

Also applies to: 268-275, 277-284


292-295: Updated default theme test: good—consider broader coverage

This assertion matches the new default. You might extend tests to cover:

  • projects_title() across themes
  • project_regular(), project_favorite(), label() across themes

This will align tests with the newly added mappings.

src/ui/components/projects_list.rs (3)

27-32: Remove commented-out “Labels” header code to avoid drift

Stale commented code tends to rot. Either delete it or gate it behind a config/feature flag.


109-114: Remove commented-out “Projects” header code

Same rationale as the Labels header: delete or gate behind a feature/setting.


83-106: Comparator does repeated linear parent lookups; consider precomputing an index

get_root_project_id and the .find() calls inside sort_by make sorting roughly O(n log n) comparisons with O(n) scans each, which can be O(n^2 log n). If project counts grow, precompute a HashMap<id, &ProjectDisplay> (or id -> parent_id) to make lookups O(1). Alternatively, build a parent -> children adjacency map and do a pre-order traversal to guarantee “parent before children” without relying on string id ordering.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a73e5a7 and 50efce2.

📒 Files selected for processing (8)
  • src/icons.rs (7 hunks)
  • src/storage.rs (2 hunks)
  • src/sync.rs (2 hunks)
  • src/todoist.rs (1 hunks)
  • src/ui/app.rs (3 hunks)
  • src/ui/components/dialogs/project_creation_dialog.rs (1 hunks)
  • src/ui/components/dialogs/task_creation_dialog.rs (1 hunks)
  • src/ui/components/projects_list.rs (4 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/storage.rs
  • src/ui/components/dialogs/task_creation_dialog.rs
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/ui/components/projects_list.rs (1)
src/icons.rs (2)
  • icons (105-111)
  • label (278-284)
src/icons.rs (1)
src/ui/app.rs (1)
  • new (57-93)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Security Audit
  • GitHub Check: Test (beta)
🔇 Additional comments (5)
src/todoist.rs (1)

80-80: Confirm Rust toolchain ≥ 1.70

I didn’t find any pin on the Rust version in your repo (no rust-toolchain* file nor rust-version in Cargo.toml). Since Option::is_some_and is stable starting in Rust 1.70, please verify or enforce a minimum toolchain:

• In Cargo.toml (root):
Under [package], add

rust-version = "1.70"

• Or add a rust-toolchain.toml at the repo root:

[toolchain]
channel = "1.70.0"

This will prevent CI/build failures on older compilers.

src/ui/components/dialogs/project_creation_dialog.rs (1)

33-41: Safer numeric conversions with f32::from: LGTM

Using f32::from avoids accidental narrowing via as casts and reads better. The min-height guards also prevent collapsing to zero-height.

src/icons.rs (1)

21-21: Defaulting to ASCII theme: confirm user-facing docs and UX expectations

Switching the default from Unicode to ASCII improves compatibility. Double-check any README/CHANGELOG and initial UI hints so users understand the new default, and that the app initialization paths (e.g., IconService::default in UI) expect ASCII-first.

src/ui/app.rs (1)

511-511: Match arms changed to Ok(()): LGTM

Tighter pattern matches; consistent with the Result<(), _> signatures of the called methods. No functional change, readability improved.

Also applies to: 558-558, 622-622

src/ui/components/projects_list.rs (1)

120-124: LGTM: favorite vs regular icon selection is clear and idiomatic

Choosing the icon via a simple conditional keeps intent obvious.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant