Skip to content

Commit 99419bb

Browse files
authored
Merge pull request #4990 from RSSNext/release/desktop/1.7.0
release(desktop): Release v1.7.0
2 parents 297fd70 + 23ac8bc commit 99419bb

74 files changed

Lines changed: 1375 additions & 558 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-android.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ on:
1414
default: preview
1515
options:
1616
- preview
17+
- production-apk
1718
- production
1819
description: "Build profile"
1920
release:
@@ -28,7 +29,7 @@ concurrency:
2829
jobs:
2930
build:
3031
name: Build Android apk for device
31-
if: github.secret_source != 'None' && (github.event_name != 'push' || !contains(github.event.head_commit.message || '', 'release(mobile):'))
32+
if: github.secret_source != 'None' && (github.event_name != 'push' || github.ref != 'refs/heads/mobile-main' || !contains(github.event.head_commit.message || '', 'release(mobile):'))
3233
runs-on: ubuntu-latest
3334

3435
steps:
@@ -75,6 +76,15 @@ jobs:
7576
- name: Build mobile web assets
7677
run: pnpm --dir apps/mobile/web-app build --outDir ../../../out/rn-web/html-renderer
7778

79+
- name: Validate release profile
80+
if: github.event.inputs.release == 'true'
81+
run: |
82+
profile="${{ github.event.inputs.profile || 'preview' }}"
83+
if [ "$profile" != "production-apk" ]; then
84+
echo "GitHub Release APKs must use the production-apk profile."
85+
exit 1
86+
fi
87+
7888
- name: 🔨 Build Android app
7989
working-directory: apps/mobile
8090
run: eas build --platform android --profile ${{ github.event.inputs.profile || 'preview' }} --local --output=${{ github.workspace }}/build.${{ github.event.inputs.profile == 'production' && 'aab' || 'apk' }}

.github/workflows/build-desktop.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ env:
3939

4040
jobs:
4141
release:
42-
if: github.secret_source != 'None' && (github.event_name != 'push' || !contains(github.event.head_commit.message || '', 'release(desktop):'))
42+
if: github.secret_source != 'None' && (github.event_name != 'push' || github.ref != 'refs/heads/main' || !contains(github.event.head_commit.message || '', 'release(desktop):'))
4343
runs-on: ${{ matrix.os }}
4444
env:
4545
PROD: ${{ github.event.inputs.tag_version == 'true' || github.ref_type == 'tag' || github.event.inputs.store == 'true' }}
@@ -278,7 +278,7 @@ jobs:
278278
apps/desktop/out/make/**/latest.yml
279279
retention-days: 90
280280

281-
- uses: signpath/github-action-submit-signing-request@v2.1
281+
- uses: signpath/github-action-submit-signing-request@v2.2
282282
continue-on-error: true
283283
if: runner.os == 'windows' && env.RELEASE == 'true' && github.event.inputs.store != 'true'
284284
with:

.github/workflows/build-ios.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ concurrency:
2323

2424
jobs:
2525
check-runner:
26-
if: github.secret_source != 'None' && (github.event_name != 'push' || !contains(github.event.head_commit.message || '', 'release(mobile):'))
26+
if: github.secret_source != 'None' && (github.event_name != 'push' || github.ref != 'refs/heads/mobile-main' || !contains(github.event.head_commit.message || '', 'release(mobile):'))
2727
runs-on: ubuntu-latest
2828
outputs:
2929
runner-label: ${{ steps.set-runner.outputs.runner-label }}

.github/workflows/sync.yaml

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,36 @@ jobs:
1717
(github.ref == 'refs/heads/main' && contains(github.event.head_commit.message || '', 'release(desktop):')) ||
1818
(github.ref == 'refs/heads/mobile-main' && contains(github.event.head_commit.message || '', 'release(mobile):'))
1919
steps:
20-
- name: Create or update sync pull request
20+
- name: Check whether source branch is ahead of dev
21+
id: compare
2122
env:
2223
GH_TOKEN: ${{ github.token }}
24+
shell: bash
2325
run: |
26+
set -euo pipefail
27+
2428
source_branch="${GITHUB_REF_NAME}"
29+
compare_ref="$(printf '%s' "dev...${source_branch}" | jq -sRr @uri)"
30+
ahead_by="$(gh api "repos/${GITHUB_REPOSITORY}/compare/${compare_ref}" --jq '.ahead_by')"
31+
32+
echo "source_branch=${source_branch}" >> "$GITHUB_OUTPUT"
33+
echo "ahead_by=${ahead_by}" >> "$GITHUB_OUTPUT"
34+
35+
if [ "$ahead_by" -eq 0 ]; then
36+
echo "No commits to sync from ${source_branch} into dev."
37+
else
38+
echo "${source_branch} is ${ahead_by} commit(s) ahead of dev."
39+
fi
40+
41+
- name: Create or update sync pull request
42+
if: steps.compare.outputs.ahead_by != '0'
43+
env:
44+
GH_TOKEN: ${{ github.token }}
45+
shell: bash
46+
run: |
47+
set -euo pipefail
48+
49+
source_branch="${{ steps.compare.outputs.source_branch }}"
2550
title="chore(sync): merge ${source_branch} into dev"
2651
body=$(cat <<EOF
2752
This pull request was created automatically after a release branch update.
@@ -31,18 +56,18 @@ jobs:
3156
EOF
3257
)
3358
34-
pr_number="$(gh pr list --base dev --head "${source_branch}" --state open --json number --jq '.[0].number')"
59+
pr_number="$(gh pr list --repo "${GITHUB_REPOSITORY}" --base dev --head "${source_branch}" --state open --json number --jq '.[0].number')"
3560
3661
if [ -z "${pr_number}" ]; then
37-
pr_url="$(gh pr create --base dev --head "${source_branch}" --title "${title}" --body "${body}")"
38-
pr_number="$(gh pr view "${pr_url}" --json number --jq '.number')"
62+
pr_url="$(gh pr create --repo "${GITHUB_REPOSITORY}" --base dev --head "${source_branch}" --title "${title}" --body "${body}")"
63+
pr_number="${pr_url##*/}"
3964
echo "Created sync PR: ${pr_url}"
4065
else
41-
gh pr edit "${pr_number}" --title "${title}" --body "${body}"
66+
gh pr edit --repo "${GITHUB_REPOSITORY}" "${pr_number}" --title "${title}" --body "${body}"
4267
echo "Updated existing sync PR: #${pr_number}"
4368
fi
4469
45-
if gh pr merge "${pr_number}" --auto --merge; then
70+
if gh pr merge --repo "${GITHUB_REPOSITORY}" "${pr_number}" --auto --merge; then
4671
echo "Enabled auto-merge for sync PR #${pr_number}"
4772
else
4873
echo "Could not enable auto-merge for sync PR #${pr_number}. Merge it manually after required checks pass."

.github/workflows/tag.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ jobs:
167167
});
168168
console.log('Desktop store build triggered successfully');
169169
170-
- name: Trigger Mobile Preview Release Build
170+
- name: Trigger Mobile Production APK Release Build
171171
if: needs.create_tag.outputs.platform == 'mobile' && needs.create_tag.outputs.ref_name == 'mobile-main' && steps.release_mode.outputs.trigger_store_builds == 'true'
172172
uses: actions/github-script@v9
173173
with:
@@ -179,11 +179,11 @@ jobs:
179179
workflow_id: 'build-android.yml',
180180
ref: 'mobile-main',
181181
inputs: {
182-
profile: 'preview',
182+
profile: 'production-apk',
183183
release: 'true'
184184
}
185185
});
186-
console.log('Mobile preview release build triggered successfully');
186+
console.log('Mobile production APK release build triggered successfully');
187187
188188
- name: Trigger Mobile Production Android Build
189189
if: needs.create_tag.outputs.platform == 'mobile' && needs.create_tag.outputs.ref_name == 'mobile-main' && steps.release_mode.outputs.trigger_store_builds == 'true'

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
<a href="https://play.google.com/store/apps/details?id=is.follow" target="_blank"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fota.folo.is%2Fversions&query=%24.store.mobile.android.version&prefix=v&style=flat-square&logo=google-play&label=Google%20Play&labelColor=black&color=FF5C00&cacheSeconds=600"/></a>
2222
<a href="https://apps.apple.com/us/app/folo-follow-everything/id6739802604"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fota.folo.is%2Fversions&query=%24.store.desktop.mas.version&prefix=v&style=flat-square&logo=apple&label=Mac%20App%20Store&labelColor=black&color=FF5C00&cacheSeconds=600" /></a>
2323
<a href="https://apps.microsoft.com/detail/9nvfzpv0v0ht?mode=direct"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fota.folo.is%2Fversions&query=%24.store.desktop.mss.version&prefix=v&style=flat-square&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMyAzaDguNTN2OC41M0gzek0xMi40NjkgM2g4LjUzdjguNTNoLTguNTN6TTMgMTIuNDdoOC41M1YyMUgzek0xMi40NjkgMTIuNDdoOC41M1YyMWgtOC41M3oiLz48L3N2Zz4%3D&logoColor=white&label=Microsoft%20Store&labelColor=black&color=FF5C00&cacheSeconds=600" /></a>
24-
<a href="https://github.com/RSSNext/Folo/releases"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fota.folo.is%2Fversions&query=%24.github.mobile.version&prefix=v&style=flat-square&logo=github&label=Mobile&labelColor=black&color=FF5C00&cacheSeconds=600" /></a>
2524
<a href="https://github.com/RSSNext/Folo/releases"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fota.folo.is%2Fversions&query=%24.github.desktop.version&prefix=v&style=flat-square&logo=github&label=Desktop&labelColor=black&color=FF5C00&cacheSeconds=600" /></a>
2625
<br />
2726
<br />

apps/desktop/changelog/1.7.0.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# What's new in v1.7.0
2+
3+
## Improvements
4+
5+
- Removed the connection status indicator from the desktop app
6+
7+
## No longer broken
8+
9+
- Fixed duplicate desktop auth session cookies
10+
- Fixed session refresh after cookie updates
11+
- Fixed returning through the Discover route
12+
- Fixed desktop download link
13+
- Fixed MAS review state detection from OTA versions
14+
- Extended API request timeouts
15+
16+
## Thanks
17+
18+
Special thanks to volunteer contributor @cuikaipeng for their valuable contribution

apps/desktop/layer/main/src/ipc/services/auth.ts

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import {
2+
buildBetterAuthSessionTokenCookieHeader,
3+
getBetterAuthSessionTokenCookieName,
4+
} from "@follow/shared/auth-cookie"
15
import { env } from "@follow/shared/env.desktop"
26
import { createAuthRequestOriginHeaders, createDesktopAPIHeaders } from "@follow/utils/headers"
37
import PKG from "@pkg"
@@ -10,8 +14,10 @@ import { WindowManager } from "~/manager/window"
1014
import {
1115
buildManagedAuthCookieHeader,
1216
buildManagedAuthCookieHeaderFromSetCookieHeader,
17+
dedupeManagedAuthCookies,
1318
getManagedAuthCookies,
1419
persistManagedAuthCookiesFromSetCookieHeader,
20+
removeManagedAuthCookies,
1521
} from "../../lib/auth-cookies"
1622
import { getCliSessionToken, syncSessionToCliConfig } from "../../lib/cli-session-sync"
1723
import { deleteNotificationsToken, updateNotificationsToken } from "../../lib/user"
@@ -40,27 +46,25 @@ export class AuthService extends IpcService {
4046
const url = new URL(apiURL)
4147
const isSecure =
4248
url.protocol === "https:" || url.hostname === "localhost" || url.hostname === "127.0.0.1"
43-
const isLocalhost = url.hostname === "localhost" || url.hostname === "127.0.0.1"
44-
const cookieNames = [
45-
BETTER_AUTH_COOKIE_NAME_SESSION_TOKEN,
46-
...(isSecure && !isLocalhost ? ["__Secure-better-auth.session_token"] : []),
47-
]
48-
49-
await Promise.all(
50-
cookieNames.map((name) =>
51-
mainWindow.webContents.session.cookies.set({
52-
url: apiURL,
53-
name,
54-
value: token,
55-
...(isLocalhost ? {} : { domain: url.hostname }),
56-
path: "/",
57-
httpOnly: true,
58-
secure: isSecure,
59-
sameSite: "no_restriction",
60-
expirationDate: new Date().setDate(new Date().getDate() + 30),
61-
}),
62-
),
63-
)
49+
const cookieName = getBetterAuthSessionTokenCookieName(apiURL)
50+
const cookieSession = mainWindow.webContents.session
51+
52+
await removeManagedAuthCookies({
53+
apiURL,
54+
session: cookieSession,
55+
names: [BETTER_AUTH_COOKIE_NAME_SESSION_TOKEN, "__Secure-better-auth.session_token"],
56+
})
57+
await cookieSession.cookies.set({
58+
url: apiURL,
59+
name: cookieName,
60+
value: token,
61+
path: "/",
62+
httpOnly: true,
63+
secure: isSecure,
64+
sameSite: "no_restriction",
65+
expirationDate: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30,
66+
})
67+
await dedupeManagedAuthCookies({ apiURL, session: cookieSession })
6468
}
6569

6670
private async clearSessionToken(): Promise<void> {
@@ -72,11 +76,7 @@ export class AuthService extends IpcService {
7276

7377
const { session } = mainWindow.webContents
7478
const apiURL = env.VITE_API_URL
75-
await Promise.allSettled([
76-
session.cookies.remove(apiURL, BETTER_AUTH_COOKIE_NAME_SESSION_TOKEN),
77-
session.cookies.remove(apiURL, "__Secure-better-auth.session_token"),
78-
session.cookies.remove(apiURL, "better-auth.last_used_login_method"),
79-
])
79+
await removeManagedAuthCookies({ apiURL, session })
8080
}
8181

8282
private async requestCredentialAuth(
@@ -171,7 +171,7 @@ export class AuthService extends IpcService {
171171
headers: this.getAuthRequestHeaders(
172172
token
173173
? {
174-
Cookie: `__Secure-better-auth.session_token=${token}; better-auth.session_token=${token}`,
174+
Cookie: buildBetterAuthSessionTokenCookieHeader(env.VITE_API_URL, token),
175175
}
176176
: undefined,
177177
),

apps/desktop/layer/main/src/lib/api-client.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { FollowClient } from "@follow-app/client-sdk"
44
import PKG, { mainHash, version as appVersion } from "@pkg"
55
import { gte } from "semver"
66

7-
import { BETTER_AUTH_COOKIE_NAME_SESSION_TOKEN } from "~/constants/app"
87
import { WindowManager } from "~/manager/window"
98
import { getCurrentRendererManifest } from "~/updater/hot-updater"
109

1110
import { logger } from "../logger"
11+
import { getPreferredSessionTokenCookie } from "./auth-cookies"
1212

1313
export const followClient = new FollowClient({
1414
credentials: "include",
@@ -39,9 +39,7 @@ followClient.addRequestInterceptor(async (ctx) => {
3939
const cookies = await window?.webContents.session.cookies.get({
4040
domain: new URL(env.VITE_API_URL).hostname,
4141
})
42-
const sessionCookie = cookies?.find((cookie) =>
43-
cookie.name.includes(BETTER_AUTH_COOKIE_NAME_SESSION_TOKEN),
44-
)
42+
const sessionCookie = cookies ? getPreferredSessionTokenCookie(cookies) : null
4543
const headerCookie = sessionCookie ? `${sessionCookie.name}=${sessionCookie.value}` : ""
4644
const userAgent = window?.webContents.getUserAgent() || `Folo/${PKG.version}`
4745

0 commit comments

Comments
 (0)