Skip to content

Conversation

@Guracc
Copy link

@Guracc Guracc commented Jan 22, 2026

Feature:
I modified the codebase to enable better compatibility out of the box with IOS imports using the aw-import-screentime utility. I also added a new visualization called BundleIDs to view the "app" attribute of the bucket.

Changes

  1. Bucket Detection (
    src/stores/buckets.ts
    )
    Updated
    bucketsAndroid
    getter to recognize buckets starting with aw-import-screentime.
  2. Query Logic (
    src/queries.ts
    )
    Fix: Modified
    canonicalEvents
    to merge Android events by ["app", "title"] instead of just ["app"].
    Reason: Previous logic stripped the title attribute during the initial query, preventing us from accessing the Human Readable Name present in iOS exports.
  3. Attribute Mapping (
    src/stores/activity.ts
    )
    Added post-processing in
    query_android
    .
    Detects iOS buckets and maps attributes to align with WebUI expectations:
    App Name (
    app
    ): Set to the Human Readable Name (from title).
    Bundle ID (classname): Set to the Bundle ID (from original
    app
    ).
    Original Title (title): Kept as Human Readable Name.
  4. Visualization (
    src/components/SelectableVisualization.vue
    )
    Enabled top_titles ("Top Window Titles") for Android sources.
    New Visualization: Added "Bundle IDs" (top_bundle_ids).
    Displays the raw Bundle ID (classname) for technical detail.
    Added to the configuration menu (gear icon).
    Verification
    Import iPhone data.
    Top Applications: Should show readable names (e.g., "YouTube") instead of bundle IDs.
    Top Window Titles: Should show readable titles.
    Bundle IDs: Select this new view to see the underlying com.google.ios.youtube style IDs.

Important

Enhance iOS import compatibility and add Bundle IDs visualization in SelectableVisualization.vue.

  • Bucket Detection:
    • Update bucketsAndroid getter in buckets.ts to recognize iOS buckets starting with aw-import-screentime.
  • Query Logic:
    • Modify canonicalEvents in queries.ts to merge Android events by ['app', 'title'].
    • Update appQuery in queries.ts to merge events by ['app', 'classname', 'title'].
  • Attribute Mapping:
    • Add post-processing in query_android in activity.ts to swap app and title for iOS buckets.
  • Visualization:
    • Add "Bundle IDs" visualization in SelectableVisualization.vue to display raw Bundle IDs.
    • Enable top_titles for Android sources in SelectableVisualization.vue.

This description was created by Ellipsis for d18d09f. You can customize this summary. It will automatically update as commits are pushed.

- buckets: detect 'aw-import-screentime' as android-compatible buckets
- queries: preserve 'title' attribute during android event merging
- activity: add post-processing to support iOS attributes (mapping 'title' to 'app' for readability)
- visualization: add 'Bundle IDs' view for technical detail while keeping 'Top Apps' human-readable
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to d18d09f in 53 seconds. Click for details.
  • Reviewed 125 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 6 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. src/components/SelectableVisualization.vue:36
  • Draft comment:
    New 'Bundle IDs' view uses window.top_titles as its data source. Confirm that reusing top_titles for iOS bundle IDs is intentional.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
2. src/queries.ts:121
  • Draft comment:
    Updated merge key for Android events now includes 'title'. Verify that this consistently preserves the human‐readable name in all cases.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
3. src/queries.ts:203
  • Draft comment:
    In appQuery, merging with keys ['app', 'classname', 'title'] ensures iOS titles are retained. Confirm that dropping other fields is acceptable for later processing.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
4. src/stores/activity.ts:321
  • Draft comment:
    iOS bucket detection is based on 'aw-import-screentime' prefix. Ensure that bucket naming remains consistent across data sources.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
5. src/stores/activity.ts:325
  • Draft comment:
    Swapping 'app' and 'title' for iOS events and re-aggregating app_events ensures standardized structure. Note that only 'app' and '$category' are retained—verify if additional fields are needed later.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
6. src/stores/buckets.ts:100
  • Draft comment:
    The bucketsAndroid getter now combines Android and iOS buckets by filtering on prefixes. Ensure that the chosen prefixes ('aw-watcher-android' and 'aw-import-screentime') cover all expected cases.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_rj1I21YyKP0WmBzS

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 22, 2026

Greptile Summary

This PR adds iOS compatibility for ActivityWatch WebUI by supporting data imported via the aw-import-screentime utility. The implementation swaps iOS attribute mappings to display human-readable app names instead of bundle identifiers.

Key Changes:

  • Bucket Detection (src/stores/buckets.ts): Detects iOS buckets by filtering 'app' type buckets starting with 'aw-import-screentime' and merges them with Android buckets
  • Query Preservation (src/queries.ts): Modified Android event merging to include "title" field alongside "app" in the initial merge, and updated appQuery to merge by ["app", "classname", "title"] instead of just ["app", "title"]
  • Attribute Mapping (src/stores/activity.ts): Added post-processing that swaps apptitle attributes for iOS buckets, setting classname to the Bundle ID and app to the human-readable name
  • Visualization (src/components/SelectableVisualization.vue): Added new "Bundle IDs" view to display raw bundle identifiers, and enabled "Top Window Titles" for Android/iOS sources

Issues Found:

  • The post-processing re-aggregation discards classname and title from app_events, keeping only app and $category, which may cause issues if downstream code expects these fields
  • Events without a title field are skipped during transformation but were already included in server-side aggregations, creating a data mismatch
  • Filtering buckets by generic type 'app' could potentially match unintended buckets beyond iOS imports

Confidence Score: 3/5

  • This PR introduces iOS support with functional logic but has potential data consistency issues that should be verified before merging.
  • The implementation successfully enables iOS compatibility, but the post-processing logic in src/stores/activity.ts manually re-aggregates events in a way that could cause data mismatches. Events without titles are skipped but were counted in server aggregations, and the re-aggregated app_events discard fields that may be expected downstream. The generic 'app' bucket type filter could also match unintended buckets.
  • Pay close attention to src/stores/activity.ts (lines 321-351) where iOS post-processing logic could cause data inconsistencies

Important Files Changed

Filename Overview
src/stores/buckets.ts Added iOS bucket detection by filtering 'app' type buckets starting with 'aw-import-screentime' and merging with Android buckets. Implementation is clean and follows existing patterns.
src/queries.ts Modified Android event merging to preserve 'title' field (adds "title" to merge keys). Also updated appQuery to merge by ["app", "classname", "title"] instead of ["app", "title"]. Changes enable iOS human-readable names to flow through.
src/stores/activity.ts Added iOS post-processing logic that swaps app/title attributes and re-aggregates events. The re-aggregation logic manually reconstructs app_events from modified title_events, which could cause inconsistencies with category data.
src/components/SelectableVisualization.vue Added new 'Bundle IDs' visualization showing classname field, and enabled 'Top Window Titles' for Android/iOS. Implementation is straightforward and follows existing patterns.

Sequence Diagram

sequenceDiagram
    participant User
    participant WebUI
    participant BucketsStore
    participant ActivityStore
    participant QueryEngine
    participant Server

    User->>WebUI: View Activity Dashboard
    WebUI->>BucketsStore: Load buckets
    BucketsStore->>Server: getBuckets()
    Server-->>BucketsStore: Return all buckets
    
    BucketsStore->>BucketsStore: bucketsAndroid(host)
    Note over BucketsStore: Filter 'currentwindow' buckets<br/>starting with 'aw-watcher-android'
    Note over BucketsStore: Filter 'app' buckets<br/>starting with 'aw-import-screentime'
    BucketsStore->>BucketsStore: Merge Android + iOS buckets
    BucketsStore-->>WebUI: Return combined bucket list
    
    WebUI->>ActivityStore: query_android(options)
    ActivityStore->>QueryEngine: Generate appQuery
    Note over QueryEngine: canonicalEvents merges by<br/>["app", "title"]
    Note over QueryEngine: title_events merge by<br/>["app", "classname", "title"]
    Note over QueryEngine: app_events merge by ["app"]
    
    ActivityStore->>Server: Execute query
    Server-->>ActivityStore: Return aggregated events
    
    alt iOS Bucket Detected
        ActivityStore->>ActivityStore: Post-process iOS events
        Note over ActivityStore: For each title_event:<br/>1. classname = original app (Bundle ID)<br/>2. app = title (Human Name)<br/>3. title = title (unchanged)
        
        ActivityStore->>ActivityStore: Re-aggregate app_events
        Note over ActivityStore: Group modified title_events by app<br/>Sum durations per app<br/>Keep only app and $category
    end
    
    ActivityStore-->>WebUI: query_window_completed(data)
    WebUI->>WebUI: Render visualizations
    Note over WebUI: Top Applications shows<br/>human-readable names
    Note over WebUI: Bundle IDs shows<br/>raw bundle identifiers
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

// Clone event to avoid reference issues
new_app_events_map[app] = { ...e, duration: 0, data: { ...e.data } };
// Ensure we only keep the 'app' key for app_events to match standard structure
new_app_events_map[app].data = { app: app, $category: e.data.$category };
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Only preserving app and $category in re-aggregated events discards classname and title which may be needed elsewhere

Suggested change
new_app_events_map[app].data = { app: app, $category: e.data.$category };
new_app_events_map[app].data = { app: app, classname: e.data.classname, $category: e.data.$category };
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/stores/activity.ts
Line: 344:344

Comment:
**logic:** Only preserving `app` and `$category` in re-aggregated events discards `classname` and `title` which may be needed elsewhere

```suggestion
            new_app_events_map[app].data = { app: app, classname: e.data.classname, $category: e.data.$category };
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +329 to +333
if (e.data.title) {
const originalApp = e.data.app;
e.data.classname = originalApp; // Bundle ID (e.g. com.google.ios.youtube)
e.data.app = e.data.title; // Human Name (e.g. YouTube)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Events without title are skipped but still contribute to aggregated durations from server-side query. This creates mismatch between title_events and app_events returned from query vs post-processed versions. Are there iOS events that legitimately don't have a title field, and if so should they be handled differently?

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/stores/activity.ts
Line: 329:333

Comment:
**logic:** Events without `title` are skipped but still contribute to aggregated durations from server-side query. This creates mismatch between `title_events` and `app_events` returned from query vs post-processed versions. Are there iOS events that legitimately don't have a title field, and if so should they be handled differently?

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +105 to +107
const ios = this.bucketsByType(host, 'app').filter((id: string) =>
id.startsWith('aw-import-screentime')
);
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Filtering by generic type 'app' could match unintended buckets. Consider using a more specific filter or adding additional validation.

The PR description mentions these are from aw-import-screentime which should have a specific bucket type. Check actual bucket type from iOS imports to ensure correct filtering. What is the actual bucket type created by aw-import-screentime - is it truly just 'app' or something more specific?

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/stores/buckets.ts
Line: 105:107

Comment:
**logic:** Filtering by generic type `'app'` could match unintended buckets. Consider using a more specific filter or adding additional validation.

The PR description mentions these are from `aw-import-screentime` which should have a specific bucket type. Check actual bucket type from iOS imports to ensure correct filtering. What is the actual bucket type created by aw-import-screentime - is it truly just 'app' or something more specific?

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

@codecov
Copy link

codecov bot commented Jan 23, 2026

Codecov Report

❌ Patch coverage is 4.54545% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.92%. Comparing base (691c57b) to head (0e48c85).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
src/stores/activity.ts 0.00% 14 Missing and 2 partials ⚠️
src/stores/buckets.ts 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #740      +/-   ##
==========================================
- Coverage   26.30%   25.92%   -0.39%     
==========================================
  Files          29       29              
  Lines        1684     1709      +25     
  Branches      288      302      +14     
==========================================
  Hits          443      443              
+ Misses       1219     1203      -16     
- Partials       22       63      +41     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ErikBjare
Copy link
Member

Hi @Guracc thanks for the changes, could you address the AI reviewer comments? Thanks :)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants