Agent Skills › emavgl/oinkoin › announcement

announcement

GitHub

用于在 Oinkoin 应用中创建和发布用户公告。涵盖编写 Markdown 内容、注册清单及更新国际化键,支持启动弹窗或页面展示,面向最终用户的内容分发任务。

.claude/skills/announcement/SKILL.md emavgl/oinkoin

Trigger Scenarios

发送面向用户的公告 显示启动对话框 发布新功能博客

Install

npx skills add emavgl/oinkoin --skill announcement -g -y
More Options

Non-standard path

npx skills add https://github.com/emavgl/oinkoin/tree/master/.claude/skills/announcement -g -y

Use without installing

npx skills use emavgl/oinkoin@announcement

指定 Agent (Claude Code)

npx skills add emavgl/oinkoin --skill announcement -a claude-code -g -y

安装 repo 全部 skill

npx skills add emavgl/oinkoin --all -g -y

预览 repo 内 skill

npx skills add emavgl/oinkoin --list

SKILL.md

Frontmatter
{
    "name": "announcement",
    "description": "Adds a new in-app announcement to Oinkoin using the announcements framework. Use when the user wants to send a user-facing announcement, show a startup dialog, or publish a blog post about a new feature.",
    "argument-hint": "<id> [title]"
}

Skill: announcement

Add a new in-app announcement to Oinkoin.

Usage

/announcement 2026-10-new-feature "New Feature X is here"

The <id> is a date-prefixed slug (YYYY-MM-slug). The title is the dialog/page heading.


How announcements work

The framework has three layers:

Layer Location Purpose
Manifest assets/docs/announcements/manifest.json Lists all announcements (id, date, title key, dialog flag)
Body assets/docs/announcements/<id>.md Markdown content shown in the dialog and announcements page
Settings Settings → Announcements Lists all entries; tapping one opens the markdown viewer

A manifest entry with "dialog": true also triggers a one-time startup dialog (dismissed permanently via SharedPreferences), shown by maybeShowAnnouncementDialog() from the Shell once authentication passes and the first frame is laid out. Add "dialogAudience" to restrict that dialog to specific builds (see Step 2).


Workflow

Step 1 — Create the markdown body

Create assets/docs/announcements/<id>.md (English only).

Rules:

  • First line should be a bold heading: **Your announcement title**
  • Keep the tone friendly and concise
  • Links are tappable in the dialog (uses flutter_markdown_plus)
  • Announcements are intentionally English-only by default — do not create translated copies unless explicitly asked

Step 2 — Register in the manifest

Add an entry to assets/docs/announcements/manifest.json:

{
  "communications": [
    {
      "id": "2026-10-new-feature",
      "date": "2026-10-15",
      "titleKey": "New Feature X is here",
      "dialog": true,
      "dialogAudience": ["free", "alpha", "debug"]
    }
  ]
}

Fields:

  • id: folder-safe slug, prefixed with date for sorting
  • date: ISO-8601 date (YYYY-MM-DD)
  • titleKey: exact English string used as the i18n key (must match en-US.json)
  • dialog: true to show a one-time startup dialog; false for page-only entries
  • dialogAudience (optional): array restricting the startup dialog to specific builds. Tags are debug/release plus the product flavor (free / alpha / dev / pro; F-Droid reports as pro). The dialog shows when any listed tag matches the running build — e.g. ["free", "alpha", "debug"] targets free-flavor users plus alpha/debug test builds. Omit or leave empty to target every build. The announcements page always lists the entry regardless of this field. Resolved by resolveBuildAudience() in lib/comms/announcement-dialog.dart.

Step 3 — Add the i18n key

The titleKey must exist in assets/locales/en-US.json as both key and value:

"New Feature X is here": "New Feature X is here"

Then run:

python3 scripts/update_en_strings.py

This syncs the key into all locale files (value = key = untranslated, which is fine since announcements are English-only).

Step 4 — Document context (optional but recommended)

Add the key to _automated_translation.json with "status": "verified" so future /translate runs don't try to translate it:

"New Feature X is here": {
  "key": "New Feature X is here",
  "context": "Title of a startup announcement dialog for Feature X",
  "file": "lib/comms/announcement-dialog.dart",
  "page": "Startup dialog + Settings > Announcements",
  "component": "Dialog title / list item title",
  "meaning": "Announcement about Feature X availability",
  "notes": "English-only announcement by decision.",
  "status": "verified"
}

Step 5 — Write the companion blog post

Every announcement also gets a blog post. Reuse the announcement markdown instead of writing from scratch: copy assets/docs/announcements/<id>.md under the frontmatter below, then expand where worthwhile (background, details, FAQ). Keep the announcement body as the condensed version.

Create website/src/content/blog/<slug>.md (slug usually matches the announcement id without the date prefix):

---
title: 'Your Blog Title'
description: 'Short description for SEO.'
pubDate: 2026-10-15
---

<announcement markdown, then expanded sections>

The blog is at https://oinkoin.com/blog/<slug>.

Link to it from the announcement body markdown: [Read more in our blog](https://oinkoin.com/blog/<slug>).

Step 6 — Verify

flutter analyze
flutter test test/communication_service_test.dart

Then test on-device:

  1. Clear app data (adb shell pm clear <package>)
  2. Launch the app
  3. Verify the dialog appears on first launch (use a build whose flavor is in dialogAudience, if set — a flutter run debug build always matches debug)
  4. Dismiss and relaunch — dialog should NOT appear again
  5. Check Settings → Announcements shows the entry (regardless of dialogAudience)

Removing an announcement

To remove the startup dialog but keep the entry visible on the announcements page:

  • Set "dialog": false in the manifest

To remove entirely:

  • Delete the .md file
  • Remove the entry from manifest.json
  • Remove the i18n key from en-US.json and re-run python3 scripts/update_en_strings.py

File reference

File Role
assets/docs/announcements/manifest.json Announcement registry
assets/docs/announcements/<id>.md Body content (English)
lib/services/communication-service.dart Service: loads manifest, resolves bodies, show-once logic
lib/comms/announcement-dialog.dart Startup dialog UI + maybeShowAnnouncementDialog() + resolveBuildAudience()
lib/shell.dart Calls maybeShowAnnouncementDialog() after auth + first frame
lib/comms/announcements-page.dart Settings list page
lib/comms/communication-detail-page.dart Markdown viewer page
lib/settings/settings-page.dart:355-369 Settings item that navigates to Announcements

Version History

  • 9971f01 Current 2026-09-23 03:02

    新增配套博客文章功能,包含 1.13.0 版本的变更日志。

  • 586baa8 2026-08-28 23:50

Same Skill Collection

.claude/skills/add-setting/SKILL.md
.claude/skills/commit/SKILL.md
.claude/skills/frameit/SKILL.md
.claude/skills/logging/SKILL.md
.claude/skills/markup-text/SKILL.md
.claude/skills/new-release/SKILL.md
.claude/skills/translate/SKILL.md
website/.claude/skills/write-article/SKILL.md

Metadata

Files
0
Version
9f47487
Hash
fb7d8de0
Indexed
2026-08-28 23:50

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-12 07:44
浙ICP备14020137号-1