mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-07-30 09:48:47 -04:00
Add CHANGELOG.md and integrate user-facing release notes with technical details into release.sh and /news page. Enhance /news with collapsible technical sections and improve localization.
This commit is contained in:
107
CHANGELOG.md
Normal file
107
CHANGELOG.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Changelog
|
||||
|
||||
Release notes for Compass. `scripts/release.sh` reads the entry for the version being tagged straight out
|
||||
of this file and uses it as the GitHub release body (falls back to `gh release --generate-notes` if no
|
||||
entry matches). That release body is what the [/news](/news) page reads, via the GitHub Releases API — so
|
||||
an entry here only reaches users once its version is actually tagged and released.
|
||||
|
||||
Each entry:
|
||||
|
||||
- Starts with `## <version>` (must match `package.json`'s `version` exactly) and ends at the next `## `
|
||||
heading or a `---` separator line — `scripts/release.sh` parses on that boundary.
|
||||
- Has two parts, in order:
|
||||
1. A **user-facing summary** — plain language, no internals. Shown by default on `/news`.
|
||||
2. A **technical details** section — implementation-level notes. Collapsed behind a "Show technical
|
||||
details" toggle on `/news`.
|
||||
- Separates those two parts with an HTML comment, `<!--tech-->`, alone on its own line. That exact marker
|
||||
is what `web/pages/news.tsx` splits on. An entry without the marker (e.g. old releases before this
|
||||
convention) just renders as-is on `/news`, with no expandable section — keep that in mind while
|
||||
backfilling.
|
||||
|
||||
To edit an already-published release's notes to match this convention, use
|
||||
`gh release edit <tag> --notes-file <(sed ...)` or paste manually in the GitHub UI — `scripts/release.sh`
|
||||
only runs at tag-creation time, so it won't touch releases that already exist.
|
||||
|
||||
---
|
||||
|
||||
## 1.13.0 — 2026-07-27
|
||||
|
||||
### New features
|
||||
|
||||
- Voice messages: record, transcribe, and play back audio directly in profiles and chats
|
||||
- Added a media creator tool for building profile photos/videos in-app
|
||||
- Added a searchable FAQ page with categories and deep links to individual answers
|
||||
- Signal is now a supported way to share contact info (phone number or signal.me link)
|
||||
- Finnish added to the list of profile languages
|
||||
- Sexual orientation is now its own profile field, with expanded gender options
|
||||
- Added neurotype and other accessibility fields to profiles
|
||||
- "Get Notified" button on saved searches — get alerted as soon as a new match appears
|
||||
- Redesigned notifications: clearer settings and empty states explaining what triggers an alert
|
||||
|
||||
### Improvements
|
||||
|
||||
- Redesigned the About page with growth stats and clearer help cards
|
||||
- Redesigned the sidebar for better accessibility and visual hierarchy
|
||||
- Saved profiles are now called "bookmarks" instead of "stars" throughout the app
|
||||
- Added a lightbox for viewing a profile's pinned photos/videos
|
||||
- Nudge to keep your account (instead of deleting it) when matches are scarce
|
||||
- Customizable share icon and a targeted share sheet for sending profiles to friends
|
||||
- Hint to help you center your face when uploading a profile picture
|
||||
- Tidied up filter labels; moved "relationship style", "raised in", and "causes" into clearer sections
|
||||
- Refined numeric-range and diet filters to handle edge cases better
|
||||
- Added a world map and demographic breakdowns to the `/stats` page
|
||||
|
||||
### Trust & safety
|
||||
|
||||
- Added a spam guard that limits new conversations per day and auto-bans abusers
|
||||
- Banned and disabled profiles no longer appear in search results
|
||||
- Added limitations for accounts flagged as suspicious
|
||||
- Added the ability to report a message channel
|
||||
|
||||
<!--tech-->
|
||||
|
||||
### Backend & API
|
||||
|
||||
- `compute-scores`: delete invalid compatibility-score rows instead of nulling them; exclude null scores
|
||||
when ordering profiles, with test coverage
|
||||
- `searchUsers`: exclude banned users and disabled profiles at the query level when `excludeUnavailable` is
|
||||
set, with unit tests
|
||||
- Hardened SQL across notification settings, private messages, and GeoDB API requests (input sanitization,
|
||||
stricter limit validation)
|
||||
- `content_owner_id` made nullable on `reports`; removed the outdated "self update" policy on `profiles`
|
||||
- Added `getChannelsCount` API endpoint
|
||||
- Refactored profile column retrieval for better caching
|
||||
- API version bumped 1.40.0 → 1.50.0 across the range
|
||||
|
||||
### Android
|
||||
|
||||
- Declared microphone permissions and runtime permission handling for voice recording
|
||||
- Added a custom icon/color for FCM push notifications
|
||||
- Added `MEDIA_SOURCE_BASE_URL` to the CD build environment
|
||||
- Bumped `compileSdkVersion`/`targetSdkVersion` to 36; app version bumped through 1.31.1 (versionCode 133)
|
||||
|
||||
### Testing
|
||||
|
||||
- Restructured the Playwright E2E suite around a POM/Fixture app-class pattern
|
||||
- Added a multi-account context manager for tests that need several accounts interacting at once
|
||||
- Added coverage for messaging, profile hiding/bookmarking, filters, onboarding, compatibility questions,
|
||||
and Google-account sign-in
|
||||
- Added DB seeding and account-cleanup helpers for test isolation
|
||||
|
||||
### Performance
|
||||
|
||||
- Reduced excessive re-renders in the rich-text editor; editor max-height is now computed dynamically
|
||||
- Added loading skeletons and avoided redundant refetches on the profiles grid
|
||||
|
||||
### Tooling & docs
|
||||
|
||||
- Added scripts for OG/social-preview card rendering, AI-generated showcase portraits, vote-tally capture,
|
||||
and demo/tour video generation (Remotion)
|
||||
- Vote-tally images switched to PNG; dropped the narrow and WebP variants
|
||||
- Added `.env.local` override support to `run_local.sh`; added dev DB/Firebase reset commands
|
||||
- Added F-Droid publishing documentation and a React/TypeScript fundamentals guide; added `CLAUDE.md` to
|
||||
several sub-packages
|
||||
|
||||
---
|
||||
|
||||
<!-- Backfill older releases above this line, following the same two-section pattern and marker described at the top of this file. -->
|
||||
@@ -642,10 +642,12 @@
|
||||
"nav.social": "Sozial",
|
||||
"nav.vote": "Abstimmung",
|
||||
"news.failed": "Abrufen der Versionen fehlgeschlagen.",
|
||||
"news.hide_technical_details": "Technische Details ausblenden",
|
||||
"news.no_release_notes": "_Keine Versionshinweise vorhanden._",
|
||||
"news.note": "Hinweis: Leider ist diese Seite nur auf Englisch verfügbar.",
|
||||
"news.seo.description": "Die neuesten Updates und Funktionen ansehen",
|
||||
"news.seo.description_general": "Alle Neuigkeiten und Code-Updates für Compass",
|
||||
"news.show_technical_details": "Technische Details anzeigen",
|
||||
"news.title": "Neuigkeiten",
|
||||
"news.view_on_github": "Auf GitHub ansehen",
|
||||
"notifications.comment.commented": "kommentierte ",
|
||||
|
||||
@@ -642,10 +642,12 @@
|
||||
"nav.social": "Social",
|
||||
"nav.vote": "Vote",
|
||||
"news.failed": "Échec de la récupération des versions.",
|
||||
"news.hide_technical_details": "Masquer les détails techniques",
|
||||
"news.no_release_notes": "_Aucune note de version fournie._",
|
||||
"news.note": "Note : Malheureusement, cette page n'est disponible qu'en anglais.",
|
||||
"news.seo.description": "Voir les dernières mises à jour et fonctionnalités",
|
||||
"news.seo.description_general": "Toutes les actualités et mises à jour du code pour Compass",
|
||||
"news.show_technical_details": "Afficher les détails techniques",
|
||||
"news.title": "Quoi de neuf",
|
||||
"news.view_on_github": "Voir sur GitHub",
|
||||
"notifications.comment.commented": "a commenté ",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "compass",
|
||||
"version": "1.12.0",
|
||||
"version": "1.13.0",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"common",
|
||||
|
||||
@@ -15,11 +15,37 @@ if [ -z "$tagged" ]; then
|
||||
git push origin "$tag"
|
||||
echo "Tagged release $tag"
|
||||
|
||||
gh release create "$tag" \
|
||||
--repo="$GITHUB_REPOSITORY" \
|
||||
--title="$tag" \
|
||||
--generate-notes
|
||||
echo "Created release"
|
||||
# Pull this version's entry out of CHANGELOG.md (see the file header for the format: a user-facing
|
||||
# summary, a `<!--tech-->` marker, then technical details). An entry ends at the next `## ` heading or a
|
||||
# `---` separator line. Falls back to --generate-notes when the version has no hand-written entry yet, so
|
||||
# releases without a changelog entry still get created.
|
||||
notes_file=$(mktemp)
|
||||
awk -v tag="$tag" '
|
||||
/^## / {
|
||||
if (found) exit
|
||||
if ($0 ~ ("^## " tag "([^0-9.]|$)")) { found=1; next }
|
||||
next
|
||||
}
|
||||
found {
|
||||
if ($0 == "---") exit
|
||||
print
|
||||
}
|
||||
' CHANGELOG.md | sed -e '/./,$!d' > "$notes_file"
|
||||
|
||||
if [ -s "$notes_file" ]; then
|
||||
gh release create "$tag" \
|
||||
--repo="$GITHUB_REPOSITORY" \
|
||||
--title="$tag" \
|
||||
--notes-file "$notes_file"
|
||||
echo "Created release from CHANGELOG.md entry"
|
||||
else
|
||||
gh release create "$tag" \
|
||||
--repo="$GITHUB_REPOSITORY" \
|
||||
--title="$tag" \
|
||||
--generate-notes
|
||||
echo "Created release (no CHANGELOG.md entry found for $tag, used --generate-notes)"
|
||||
fi
|
||||
rm -f "$notes_file"
|
||||
|
||||
# Release to ...
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {ChevronDownIcon, ChevronUpIcon} from '@heroicons/react/24/solid'
|
||||
import {githubRepoSlug} from 'common/constants'
|
||||
import {useEffect, useState} from 'react'
|
||||
import {Col} from 'web/components/layout/col'
|
||||
import {Row} from 'web/components/layout/row'
|
||||
import {CustomLink} from 'web/components/links'
|
||||
import {CustomMarkdown} from 'web/components/markdown'
|
||||
import {EnglishOnlyWarning} from 'web/components/news/english-only-warning'
|
||||
@@ -11,6 +13,22 @@ import {useT} from 'web/lib/locale'
|
||||
import {getPageData} from 'web/lib/util/page-data'
|
||||
import {isNativeMobile} from 'web/lib/util/webview'
|
||||
|
||||
// Release notes are written with a user-facing summary followed by a technical section, separated by this
|
||||
// marker on its own line (see CHANGELOG.md). Only the summary renders by default; the technical section is
|
||||
// tucked behind a toggle. Releases predating this convention have no marker, so they render as-is.
|
||||
const TECHNICAL_SECTION_MARKER = '<!--tech-->'
|
||||
|
||||
function splitReleaseNotes(body: string): {summary: string; technical: string | null} {
|
||||
const markerIndex = body.indexOf(TECHNICAL_SECTION_MARKER)
|
||||
if (markerIndex === -1) {
|
||||
return {summary: body, technical: null}
|
||||
}
|
||||
return {
|
||||
summary: body.slice(0, markerIndex).trim(),
|
||||
technical: body.slice(markerIndex + TECHNICAL_SECTION_MARKER.length).trim(),
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchReleases() {
|
||||
const releases = await fetch(`https://api.github.com/repos/${githubRepoSlug}/releases`)
|
||||
.then((r) => r.json())
|
||||
@@ -109,32 +127,7 @@ export default function WhatsNew(props: {releases?: Release[]}) {
|
||||
<Col className="max-w-3xl mx-auto py-8 px-4 custom-link gap-6">
|
||||
<EnglishOnlyWarning />
|
||||
{releases.map((release: Release) => (
|
||||
<div
|
||||
key={release.id}
|
||||
className="bg-canvas-50 border border-canvas-200 rounded-xl p-6 transition-all hover:border-primary-300 hover:shadow-sm"
|
||||
>
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<h2 className="font-heading text-2xl font-medium text-ink-900 leading-tight">
|
||||
{release.name || release.tag_name}
|
||||
</h2>
|
||||
<span className="text-sm text-ink-300 font-mono whitespace-nowrap ml-4">
|
||||
{new Date(release.published_at).toISOString().split('T')[0]}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mb-5 prose prose-neutral dark:prose-invert text-ink-900">
|
||||
<CustomMarkdown>
|
||||
{formatPullLinks(
|
||||
release.body || t('news.no_release_notes', '_No release notes provided._'),
|
||||
)}
|
||||
</CustomMarkdown>
|
||||
</div>
|
||||
<CustomLink
|
||||
href={release.html_url}
|
||||
className="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 text-sm font-medium transition-colors"
|
||||
>
|
||||
{t('news.view_on_github', 'View on GitHub')}
|
||||
</CustomLink>
|
||||
</div>
|
||||
<ReleaseCard key={release.id} release={release} />
|
||||
))}
|
||||
</Col>
|
||||
)}
|
||||
@@ -142,6 +135,62 @@ export default function WhatsNew(props: {releases?: Release[]}) {
|
||||
)
|
||||
}
|
||||
|
||||
function ReleaseCard(props: {release: Release}) {
|
||||
const {release} = props
|
||||
const t = useT()
|
||||
const [showTechnical, setShowTechnical] = useState(false)
|
||||
|
||||
const {summary, technical} = splitReleaseNotes(
|
||||
formatPullLinks(release.body || t('news.no_release_notes', '_No release notes provided._')),
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="bg-canvas-50 border border-canvas-200 rounded-xl p-6 transition-all hover:border-primary-300 hover:shadow-sm">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<h2 className="font-heading text-2xl font-medium text-ink-900 leading-tight">
|
||||
{release.name || release.tag_name}
|
||||
</h2>
|
||||
<span className="text-sm text-ink-300 font-mono whitespace-nowrap ml-4">
|
||||
{new Date(release.published_at).toISOString().split('T')[0]}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mb-5 prose prose-neutral dark:prose-invert text-ink-900">
|
||||
<CustomMarkdown>{summary}</CustomMarkdown>
|
||||
</div>
|
||||
{technical && (
|
||||
<div className="mb-5">
|
||||
<button
|
||||
onClick={() => setShowTechnical(!showTechnical)}
|
||||
className="text-primary-500 hover:text-primary-700 z-10 select-none text-sm"
|
||||
>
|
||||
<Row className="items-center gap-0.5">
|
||||
{showTechnical ? (
|
||||
<ChevronUpIcon className="h-4 w-4" />
|
||||
) : (
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
)}
|
||||
{showTechnical
|
||||
? t('news.hide_technical_details', 'Hide technical details')
|
||||
: t('news.show_technical_details', 'Show technical details')}
|
||||
</Row>
|
||||
</button>
|
||||
{showTechnical && (
|
||||
<div className="mt-3 prose prose-neutral dark:prose-invert text-ink-900">
|
||||
<CustomMarkdown>{technical}</CustomMarkdown>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<CustomLink
|
||||
href={release.html_url}
|
||||
className="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 text-sm font-medium transition-colors"
|
||||
>
|
||||
{t('news.view_on_github', 'View on GitHub')}
|
||||
</CustomLink>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function formatPullLinks(text = '') {
|
||||
return text
|
||||
.replace('CompassMeet', 'CompassConnections')
|
||||
|
||||
Reference in New Issue
Block a user