Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
.idea/
.vscode/
.qoder/
.claude/
.dbg/

# Logs
logs/
Expand Down
23 changes: 0 additions & 23 deletions debug-autostart-not-registering.md

This file was deleted.

90 changes: 90 additions & 0 deletions desktop/PRODUCT_REQUIREMENTS_0.1.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# PinWall Desktop 0.1.3 Product Requirements

## Theme

Official Widget Hub.

## Goal

Make PinWall's existing local widget capability usable for normal desktop users. Users should be able to discover official widgets, understand requested permissions, install them with one action, and manage installed widgets without using a file picker as the primary path.

## Scope

- Add an official widget catalog in Settings.
- Support one-click installation for bundled official widgets.
- Keep local widget installation available as an advanced trusted-source path.
- Improve permission explanations and risk visibility.
- Improve installed widget management: enable, disable, remove, source, version, and permissions.
- Show user-visible status for install and uninstall success/failure.

## Official Widgets

The initial official catalog uses bundled widgets from `../widgets`:

- Clock: `com.pinwall.clock`
- Weather: `com.pinwall.weather`
- Pomodoro: `com.pinwall.pomodoro`
- System Monitor: `com.pinwall.system-monitor`
- Music Control: `com.pinwall.music`

## Permission Model

Permission risk levels:

- Low: `theme`, `i18n`, `app`
- Medium: `storage`, `notify`, `events`
- High: `network`, `system`, `cards`, `ai`

Requirements:

- Every widget row shows permission chips.
- High-risk permissions are visually distinct.
- Each permission has a plain-language explanation.
- Installing a widget with high-risk permissions requires explicit confirmation.

## Installation

Official install:

- User clicks Install in the official catalog.
- App installs the corresponding bundled widget directory.
- Widget is added to the widget store and enabled by default.
- Desktop renders the widget immediately.
- Settings shows success or failure feedback.

Local install:

- Remains available under an Advanced local install action.
- Copy explains that users should install only trusted widgets.
- Existing manifest, path, enum, file existence, and symlink validation remains required.

## Installed Management

Installed widget rows must support:

- Enable/disable.
- Remove.
- View version, source, category, and default size.
- View permissions and permission explanations.

## Non-goals

- Public marketplace.
- Remote widget download.
- Third-party review workflow.
- Paid widgets.
- Widget auto-update.
- Full SDK documentation site.

## Acceptance Criteria

- Official widget catalog is visible in Settings.
- All five bundled official widgets are listed.
- Official widgets can be installed from Settings without choosing a folder.
- Installed widgets appear on the desktop immediately.
- Installed widgets can be enabled, disabled, and removed.
- Permission chips and explanations are visible for official and installed widgets.
- High-risk permissions require confirmation before installation.
- Local install is still available but marked as advanced/trusted-source only.
- Install and uninstall failures show user-visible feedback.
- `pnpm test:run`, `pnpm build`, and `cargo test` pass before release.
10 changes: 5 additions & 5 deletions desktop/RELEASE_PROCESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ This document describes how to publish a desktop release to GitHub Releases.

## Release Target

- Current release: `v0.1.1`
- Current release: `v0.1.3`
- GitHub Releases: https://github.com/you-want/PinWall/releases
- Release workflow: `.github/workflows/release.yml`

## What The Automation Does

Pushing a tag like `v0.1.1` runs the `Release` workflow.
Pushing a tag like `v0.1.3` runs the `Release` workflow.

The workflow:

Expand Down Expand Up @@ -60,8 +60,8 @@ Then commit the release changes.
## Publish By Tag

```bash
git tag v0.1.1
git push origin v0.1.1
git tag v0.1.3
git push origin v0.1.3
```

After the workflow completes, check:
Expand All @@ -76,7 +76,7 @@ The workflow also supports manual dispatch from GitHub Actions.
Use the `Release` workflow and input:

```text
v0.1.1
v0.1.3
```

Manual dispatch is useful for rerunning a failed release job, but tag-based release is preferred.
Expand Down
27 changes: 21 additions & 6 deletions desktop/RELEASE_QA.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ Current local note:
- [ ] Quota monitor can be enabled/disabled.
- [ ] Care reminder toggles and parameters persist.
- [ ] Care reminders explain that they appear as top-right notifications instead of desktop cards.
- [ ] Widget extension section only presents local install as the production path.
- [ ] Marketplace is clearly marked experimental and is not presented as a release-ready store.
- [ ] Installed widgets show their requested permissions.
- [ ] Widget extension section presents the Official Widget Hub as the primary path.
- [ ] Local folder install remains available only as an advanced trusted-source path.
- [ ] Marketplace is not presented as a release-ready store.
- [ ] Official and installed widgets show requested permissions with plain-language explanations.
- [ ] Network, system, cards, and AI permissions are visually distinguishable from low-risk permissions.

## Unified Care Reminders
Expand All @@ -124,12 +125,26 @@ Current local note:
- [ ] Dismissing or auto-dismissing a notification does not delete user notes.
- [ ] User-created note reminders still keep their original note after notification.

## Official Widget Hub

This is the main widget path for 0.1.3.

- [ ] All five official widgets are listed: Clock, Weather, Pomodoro, System Monitor, and Music Control.
- [ ] Install Clock from the Official Widget Hub without choosing a folder.
- [ ] Install Weather and confirm the high-risk `network` permission prompt appears before install.
- [ ] Install System Monitor and confirm the high-risk `system` permission prompt appears before install.
- [ ] Installed widgets appear on the main wall immediately.
- [ ] Installed widgets survive app quit and restart.
- [ ] Installed widgets can be toggled off and on.
- [ ] Installed widgets can be removed.
- [ ] Removing all optional cards and widgets does not leave an empty side panel.

## Widget Local Install

This is an experimental feature for 0.1.x.
This is an advanced trusted-source path for 0.1.3.

- [ ] Install one official local widget directory from `../widgets`.
- [ ] The widget appears on the desktop.
- [ ] Install one trusted local widget directory from `../widgets`.
- [ ] The widget appears on the main wall.
- [ ] The widget can be toggled off and on.
- [ ] The widget can be removed.
- [ ] Installing a widget with an invalid id is rejected.
Expand Down
9 changes: 4 additions & 5 deletions desktop/e2e/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ test.describe('PinWall E2E Tests', () => {
await expect(page.locator('.app-container')).toBeVisible();
});

test('shows empty hint when no cards', async ({ page }) => {
test('renders wall content after startup', async ({ page }) => {
await page.goto('http://localhost:1930');
// The app should show the empty state hint
const hasHint = await page.locator('.empty-hint, .loading').isVisible();
expect(hasHint).toBe(true);
await expect(page.locator('.loading')).not.toBeVisible();
await expect(page.locator('.empty-hint, .pin-card, .wall-side-panel').first()).toBeVisible();
});

test('floating buttons are visible', async ({ page }) => {
Expand All @@ -32,7 +31,7 @@ test.describe('PinWall E2E Tests', () => {

const titleInput = page.locator('#card-title');
await expect(titleInput).toBeVisible();
await expect(titleInput).toHaveValue('新建便签');
await expect(titleInput).toHaveValue(/^(新建便签|New Note)$/);

const contentTextarea = page.locator('#card-content');
await expect(contentTextarea).toBeVisible();
Expand Down
2 changes: 1 addition & 1 deletion desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "desktop",
"private": true,
"version": "0.1.1",
"version": "0.1.3",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
45 changes: 45 additions & 0 deletions desktop/releases/v0.1.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# PinWall Desktop v0.1.3

This release makes the local widget system usable for normal desktop users through an official bundled widget hub.

## What's New

- Added an Official Widget Hub in Settings.
- Added one-click install for five bundled official widgets:
- Clock
- Weather
- Pomodoro
- System Monitor
- Music Control
- Official widgets are bundled inside the macOS app resources.
- Installed widgets render in the main wall side panel and persist after restart.
- Installed widgets can be enabled, disabled, updated, and removed from Settings.

## Widget Safety

- Widget permission chips now show plain-language explanations.
- High-risk permissions are visually distinct.
- Installing widgets with `network`, `system`, `cards`, or `ai` permissions requires confirmation.
- Local folder install remains available as an advanced trusted-source path.
- Widget entry HTML is loaded through the host command path, with manifest id, path, enum, file existence, and symlink validation still enforced.

## Included Widget Updates

- Refreshed Clock, Weather, Pomodoro, System Monitor, and Music widgets.
- Added SVG icons for all bundled official widgets.
- Weather and Pomodoro widgets include additional settings and sizing updates.
- Music widget uses the system bridge media fallback.

## Validation

- Frontend unit tests: `pnpm test:run`
- Frontend production build: `pnpm build`
- Rust tests: `cargo test`
- Playwright smoke tests: `pnpm test:e2e`
- macOS app bundle: `pnpm tauri:build:app`

## Known Notes

- Public widget marketplace, remote widget download, paid widgets, and third-party review workflow are still out of scope.
- Local install should be used only with trusted widget folders.
- The local app bundle build was verified. Public DMG packaging should still be verified by the release workflow before publishing.
2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "desktop"
version = "0.1.1"
version = "0.1.3"
description = "A Tauri App"
authors = ["you"]
edition = "2021"
Expand Down
2 changes: 2 additions & 0 deletions desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ pub fn run() {
tray::update_shortcut_display,
widgets::list_installed_widgets,
widgets::install_widget,
widgets::install_official_widget,
widgets::read_widget_entry_html,
widgets::uninstall_widget,
widgets::read_widget_storage,
widgets::write_widget_storage,
Expand Down
Loading
Loading