diff --git a/widgets/raindrop-bookmarks/README.md b/widgets/raindrop-bookmarks/README.md new file mode 100644 index 00000000..0ad4f773 --- /dev/null +++ b/widgets/raindrop-bookmarks/README.md @@ -0,0 +1,670 @@ +# Raindrop Bookmarks Widget + +A comprehensive Raindrop.io bookmarks widget that displays your groups, collections, sub-collections, and bookmarks with full three-level hierarchy support. + +![Preview](preview.png) + +Raindrop.io extension view (reference) — how your saved bookmarks map into the rendered layout. + +![Raindrop extension reference](raindrop-extension-reference.png) + +## Features + +- 📁 **Three-Level Hierarchy**: Display groups, collections, and sub-collections with proper ordering +- 🗂ïļ **Custom Sorting**: Respects your Raindrop.io group organization and collection order +- 🔖 **Bookmark Details**: Shows cover images, titles, tags, and creation dates +- ðŸŽĻ **Collection Colors**: Visual color indicators for each collection +- 🔄 **Auto-refresh**: 24-hour cache with manual refresh support +- âœĻ **Auto-expand Options**: Configure which groups and collections open by default +- 🔗 **Quick Access**: Click widget title to open Raindrop.io +- 🔐 **Token Error Handling**: Automatic redirect to settings page when token expires + +## Configuration + +```yaml +- type: custom-api + title: 📚 Raindrop + title-url: https://app.raindrop.io/ + url: https://api.raindrop.io/rest/v1/collections + headers: + Authorization: Bearer ${RAINDROP_TOKEN} + cache: 1d + template: | + {{/* Configuration options */}} + {{ $autoOpen := "first" }} {{/* "none"=collapse all, "all"=expand all, "first"=expand first level, or regex pattern */}} + {{ $autoOpenChildren := false }} {{/* In regex mode, also expand all children of matched nodes */}} + {{ $showCover := true }} {{/* Show cover images for bookmarks */}} + + {{/* Fetch user data for groups */}} + {{ $userReq := newRequest "https://api.raindrop.io/rest/v1/user" + | withHeader "Authorization" "Bearer ${RAINDROP_TOKEN}" + | getResponse + }} + + {{/* Fetch child collections */}} + {{ $childrensReq := newRequest "https://api.raindrop.io/rest/v1/collections/childrens" + | withHeader "Authorization" "Bearer ${RAINDROP_TOKEN}" + | getResponse + }} + + {{/* Fetch recent raindrops (latest 50) */}} + {{ $raindropsReq := newRequest "https://api.raindrop.io/rest/v1/raindrops/0" + | withParameter "perpage" "50" + | withHeader "Authorization" "Bearer ${RAINDROP_TOKEN}" + | getResponse + }} + + {{/* Check if all API calls succeeded */}} + {{ if and (eq .Response.StatusCode 200) (eq $userReq.Response.StatusCode 200) (eq $childrensReq.Response.StatusCode 200) (eq $raindropsReq.Response.StatusCode 200) }} + {{ $allCollections := .JSON.Array "items" }} + {{ $userGroups := $userReq.JSON.Array "user.groups" }} + {{ $childCollections := $childrensReq.JSON.Array "items" }} + {{ $allRaindrops := $raindropsReq.JSON.Array "items" }} + + + + {{/* Main groups list */}} +
+ +
+ + {{/* Bottom Link */}} +
+ + Raindrop.io + + +
+ + {{ else }} + {{/* Error handling */}} +
+

⚠ïļ Failed to Load Data

+
+

Please check the following:

+ +
+ API Response Status: +
    +
  • Collections: {{ .Response.StatusCode }} - {{ .Response.Status }}
  • +
  • User Data: {{ $userReq.Response.StatusCode }} - {{ $userReq.Response.Status }}
  • +
  • Child Collections: {{ $childrensReq.Response.StatusCode }} - {{ $childrensReq.Response.Status }}
  • +
  • Raindrops: {{ $raindropsReq.Response.StatusCode }} - {{ $raindropsReq.Response.Status }}
  • +
+
+
+
+ {{ end }} +``` + +## Environment Variables + +### Required + +- `RAINDROP_TOKEN`: Your Raindrop.io API token + +### How to Get Your Token + +1. Visit [Raindrop.io Settings - Integrations](https://app.raindrop.io/settings/integrations) +2. Click "Create new app" or use an existing one +3. Generate a test token +4. Copy the token and add it to your Glance configuration environment file. + +## Customization + +### Configuration Options + +The template includes several configuration variables at the top: + +```yaml +{{ $autoOpen := "first" }} # "none" | "all" | "first" | regex pattern +{{ $autoOpenChildren := false }} # regex mode: expand matched node's children too +{{ $showCover := true }} # Show cover images for bookmarks +``` + +#### `$autoOpen` + +| Value | Behavior | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `"none"` | All groups/collections collapsed | +| `"all"` | All groups/collections expanded | +| `"first"` | All groups expanded + first collection in first group expanded (backward compatible default) | +| regex | Nodes whose name matches the pattern are expanded. **Ancestor nodes are automatically expanded** (cascade up). Example: `"^(Quick Link)$"` expands "Quick Link" and its parent group | + +#### `$autoOpenChildren` + +Only effective in regex mode: + +- `false`: Only expand matched nodes (and their ancestors) +- `true`: Expand matched nodes + all their descendant children + +#### Examples + +```yaml +# Example 1: Only expand the collection named "Quick Link" (parent group auto-expands) +{{ $autoOpen := "^(Quick Link)$" }} +{{ $autoOpenChildren := false }} + +# Example 2: Expand "Quick Link" and all its sub-collections +{{ $autoOpen := "^(Quick Link)$" }} +{{ $autoOpenChildren := true }} + +# Example 3: Expand a group and all collections + sub-collections under it +{{ $autoOpen := "^(Bookmarks)$" }} +{{ $autoOpenChildren := true }} + +# Example 4: Multiple targets +{{ $autoOpen := "^(Bookmarks|Entertainment|Tech)$" }} +{{ $autoOpenChildren := true }} +``` + +- **`$showCover`**: Set to `true` to display cover images for bookmarks, `false` to hide them and show only text + +### Responsive Grid Layout + +The widget automatically adjusts the number of columns based on the container width using container queries: + +- **> 700px**: 3 columns + +![over 700 pixel](preview-1.png) + +- **450px - 700px**: 2 columns + +![between 450 and 700 pixel](preview-2.png) + +- **< 450px**: 1 column (mobile) with optimized compact layout: + - Cover images reduced to 24px × 24px + - Date and tag text size reduced to `--font-size-h5` + +![lower than 640 pixel](preview-3.png) + +### Cache Duration + +Default cache is 24 hours (`1d`). You can adjust this: + +```yaml +cache: 12h # 12 hours +cache: 30m # 30 minutes +cache: 1w # 1 week +``` + +### Widget Title + +You can customize the widget title: + +```yaml +title: 🔖 My Bookmarks +title: 📚 Reading List +``` + +## API Usage & Structure + +### Three-Level Hierarchy + +The widget uses multiple Raindrop API endpoints to build a complete hierarchy: + +1. **Groups** (Layer 1): Fetched from `/user` endpoint - Your custom organizational groups +2. **Collections** (Layer 2): Fetched from `/collections` endpoint - Sorted by group membership +3. **Sub-collections** (Layer 3): Fetched from `/collections/childrens` endpoint - Nested under collections +4. **Bookmarks**: Fetched from `/raindrops/0` endpoint - The 50 most recent items + +### API Limitations + +- The widget displays the **50 most recent bookmarks** due to Raindrop API's per-page limit +- **Within each group, only 2 levels of nesting are supported**: collections (Layer 2) and their direct sub-collections (Layer 3). Deeper nested sub-collections under a sub-collection will not be displayed. +- Collections are ordered according to your Raindrop.io group settings +- Hidden groups are automatically filtered out + +## Troubleshooting + +### Token Expired + +If your token expires (HTTP 401), the widget will automatically display a link to generate a new token at [Raindrop Settings](https://app.raindrop.io/settings/integrations). + +### No Bookmarks Showing + +- Ensure you have bookmarks in your Raindrop account +- Check that the `RAINDROP_TOKEN` environment variable is correctly set +- Verify your token has not expired + +### Groups or Collections Not Expanding + +- Make sure you're clicking on the group/collection name or folder icon +- Some collections may be empty or have no bookmarks in the recent 50 items +- Check the `$autoOpen` configuration option + +### Collections Not Showing in Groups + +- Ensure your collections are assigned to groups in Raindrop.io +- Hidden groups won't be displayed (check group settings in Raindrop.io) + +## Credits + +- Uses [Raindrop.io API](https://developer.raindrop.io) + diff --git a/widgets/raindrop-bookmarks/meta.yml b/widgets/raindrop-bookmarks/meta.yml new file mode 100644 index 00000000..a7514fb9 --- /dev/null +++ b/widgets/raindrop-bookmarks/meta.yml @@ -0,0 +1,4 @@ +title: Thorough Raindrop Bookmarks +description: Display your Raindrop.io bookmarks with hierarchical collections, cover images, tags, and dates. +author: wen-hsiu-hsu + diff --git a/widgets/raindrop-bookmarks/preview-1.png b/widgets/raindrop-bookmarks/preview-1.png new file mode 100644 index 00000000..4ccef054 Binary files /dev/null and b/widgets/raindrop-bookmarks/preview-1.png differ diff --git a/widgets/raindrop-bookmarks/preview-2.png b/widgets/raindrop-bookmarks/preview-2.png new file mode 100644 index 00000000..83240d23 Binary files /dev/null and b/widgets/raindrop-bookmarks/preview-2.png differ diff --git a/widgets/raindrop-bookmarks/preview-3.png b/widgets/raindrop-bookmarks/preview-3.png new file mode 100644 index 00000000..6b208267 Binary files /dev/null and b/widgets/raindrop-bookmarks/preview-3.png differ diff --git a/widgets/raindrop-bookmarks/preview.png b/widgets/raindrop-bookmarks/preview.png new file mode 100644 index 00000000..5892b2ad Binary files /dev/null and b/widgets/raindrop-bookmarks/preview.png differ diff --git a/widgets/raindrop-bookmarks/raindrop-extension-reference.png b/widgets/raindrop-bookmarks/raindrop-extension-reference.png new file mode 100644 index 00000000..702da024 Binary files /dev/null and b/widgets/raindrop-bookmarks/raindrop-extension-reference.png differ