Skip to content

Commit ab0ef8b

Browse files
committed
Gate Safari behavior by build target
1 parent f40b2d9 commit ab0ef8b

14 files changed

Lines changed: 176 additions & 67 deletions

.env.example

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33
# code; non-prefixed vars are silently ignored.
44

55
# ---------------------------------------------------------------------------
6-
# OPTIONAL — only needed for reverse proxy video mode and zen music.
6+
# REQUIRED for Chrome builds — build fails fast if missing.
7+
# Optional for `npm run build:safari`.
78
#
89
# Macify CDN base URL. Single host that serves both:
910
# - GET <BASE>/itunes-assets/... → reverse proxy to sylvan.apple.com
1011
# - GET <BASE>/music/musicNNNNN.mp3 → R2 bucket of zen-mode music
1112
#
12-
# Leave this unset for the Safari self-use build. The extension defaults to
13-
# direct Apple streaming from https://sylvan.apple.com with no local videos.
14-
#
1513
# Set up: deploy cloudflare-worker/worker.js to a Worker route on
1614
# <BASE>/itunes-assets/*, and bind your music R2 bucket to <BASE>.
1715
# No trailing slash.

README.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
# Macify — macOS Aerial Screensavers in Safari or Chrome's New Tab
1+
# Macify — macOS Aerial Screensavers in Chrome's New Tab
22

33
![GitHub Repo stars](https://img.shields.io/github/stars/jason5ng32/macOS-Screen-Saver-as-Chrome-New-Tab)
44
![GitHub](https://img.shields.io/github/license/jason5ng32/macOS-Screen-Saver-as-Chrome-New-Tab)
55
![Chrome Web Store Version](https://img.shields.io/chrome-web-store/v/lgdipcalomggcjkohjhkhkbcpgladnoe)
66
![GitHub contributors](https://img.shields.io/github/contributors/jason5ng32/macOS-Screen-Saver-as-Chrome-New-Tab)
77

8-
Replace Safari or Chrome's new tab page with macOS's aerial screensaver videos and a small set of calm, optional widgets. macOS is **not** required — videos are streamed from Apple's CDN.
8+
Replace Chrome's new tab page with macOS's aerial screensaver videos and a small set of calm, optional widgets. macOS is **not** required — videos are streamed from Apple's CDN and play in any platform that runs Chrome.
99

1010
![screenshot](docs/screenshot.png)
1111

1212
## Features
1313

1414
- 🎥 **156 aerial videos** in 4K SDR, sourced from Apple's current macOS catalog (Landscapes, Cities, Underwater, Space, and more).
1515
- 🌤️ **Live weather** — current temperature, "feels like", 3-day forecast, sunrise/sunset, UV, wind, air quality. Powered by [Open-Meteo](https://open-meteo.com/), no API key required.
16-
- 📌 **Top sites** widget pulled from the browser's built-in list when available (no history permission needed).
16+
- 📌 **Top sites** widget pulled from Chrome's built-in list (no history permission needed).
1717
- 💬 **Random quotes** from a curated 500-entry public-domain set.
1818
- 🧘 **Zen mode** — fullscreen the video with optional ambient music.
1919
- 🔤 **4 languages** — English, 简体中文, 繁體中文, 日本語.
@@ -22,19 +22,20 @@ Replace Safari or Chrome's new tab page with macOS's aerial screensaver videos a
2222

2323
[Install from Chrome Web Store](https://chromewebstore.google.com/detail/macify-macos-screensaver/lgdipcalomggcjkohjhkhkbcpgladnoe).
2424

25-
Or load unpacked: see [Building from source](#building-from-source). For a local Safari build, see [SAFARI.md](SAFARI.md).
25+
Or load unpacked: see [Building from source](#building-from-source). For an
26+
experimental local Safari build, see [SAFARI.md](SAFARI.md).
2627

2728
## Choosing a video source
2829

2930
Three options. Each section in the extension's settings page also includes a built-in step-by-step setup guide — this README only summarises.
3031

3132
### 1. Apple Server (default)
3233

33-
Streams directly from `sylvan.apple.com`. If direct video playback fails, two fallback paths are available:
34+
Streams directly from `sylvan.apple.com`. Chrome may not trust Apple's certificate by default; two ways to fix it:
3435

35-
**Option A — Reverse proxy.** Video requests are routed through your own Cloudflare Worker. Convenient, but it requires a CDN host you control.
36+
**Option A — Reverse proxy (default on, easiest).** Video requests are routed through a hosted Cloudflare Worker that handles the certificate dance. Zero local setup. Convenient but should not be relied on long-term — set up local hosting or trust the cert when possible.
3637

37-
**Option B — Trust Apple's cert manually.** Visit [https://sylvan.apple.com](https://sylvan.apple.com) once in the target browser. If you see a security warning, use the browser's advanced option to proceed. The browser should remember that trust.
38+
**Option B — Trust Apple's cert manually (cleanest).** Visit [https://sylvan.apple.com](https://sylvan.apple.com) once in Chrome. You'll see a security warning — click "Advanced", then "Proceed to sylvan.apple.com (unsafe)". Chrome remembers the trust and direct connection works thereafter.
3839

3940
![Chrome warning when trusting sylvan.apple.com](docs/chromewarnning.jpg)
4041

@@ -84,20 +85,21 @@ In Macify settings, switch the source to **Local server** and confirm the URL is
8485

8586
## Permissions
8687

87-
Macify requests two permissions, both non-sensitive:
88+
Macify requests three permissions, all non-sensitive:
8889

8990
| Permission | Used for |
9091
|---|---|
9192
| `storage` | Persist user preferences and cache weather data. |
92-
| `topSites` | Read the browser's most-visited list for the Top Sites widget when supported. |
93+
| `topSites` | Read Chrome's most-visited list for the Top Sites widget. |
94+
| `favicon` | Show favicons next to Top Sites entries (uses Chrome's built-in cache; no external network). |
9395

9496
No `history` permission. No host permissions for arbitrary sites.
9597

9698
## Building from source
9799

98100
Requirements: Node.js 20+ and npm.
99101

100-
The default self-use build is zero-config: it streams directly from Apple and does not require a CDN. A CDN is only needed for the optional Apple aerial reverse proxy and zen-mode music.
102+
The build is **not zero-config** — Macify needs a CDN you control for the Apple aerial reverse proxy and the zen-mode music. The published Chrome Store build uses my own infrastructure; if you fork, you bring your own. The build refuses to run without these set.
101103

102104
### 1. Stand up your CDN host
103105

@@ -133,13 +135,13 @@ Skip this if you don't care — the worker still works.
133135
git clone https://github.com/jason5ng32/macOS-Screen-Saver-as-Chrome-New-Tab.git
134136
cd macOS-Screen-Saver-as-Chrome-New-Tab
135137
cp .env.example .env
136-
# edit .env only if you want VITE_MACIFY_BASE for proxy/music
138+
# edit .env — fill in VITE_MACIFY_BASE (required)
137139
# and VITE_APPLE_PROXY_KEY (only if you set up the WAF rule above)
138140
npm install
139141
npm run build
140142
```
141143

142-
See [`.env.example`](.env.example) for the full optional environment reference.
144+
If `.env` is missing or incomplete the build aborts with a list of what's missing. See [`.env.example`](.env.example) for the full reference.
143145

144146
### 3. Load the extension
145147

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
"type": "module",
88
"scripts": {
99
"dev": "vite",
10-
"build": "vite build",
11-
"build:safari": "vite build && node scripts/prepare-safari-dist.mjs",
10+
"build": "vite build --mode chrome",
11+
"build:safari": "vite build --mode safari && node scripts/prepare-safari-dist.mjs",
1212
"package:safari": "npm run build:safari && xcrun safari-web-extension-packager dist --macos-only",
1313
"preview": "vite preview",
1414
"zip": "node scripts/zip.js",

scripts/prepare-safari-dist.mjs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,55 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
66
const root = resolve(__dirname, '..');
77
const dist = resolve(root, 'dist');
88
const manifestPath = resolve(dist, 'manifest.json');
9+
const safariLocaleOverrides = {
10+
en: {
11+
ext_description:
12+
"Transform your new tab into macOS's gorgeous aerial screensaver videos.",
13+
video_apple_help_intro:
14+
"Some browsers may not trust Apple's sylvan.apple.com certificate, so direct video loading can fail. Two ways to make it work:",
15+
video_apple_help_option2_body_post:
16+
'in the target browser once. If you see a security warning, open the advanced option and proceed. The browser should remember your trust after that.',
17+
options_translation_description:
18+
'Translates English mottos into your display language when the browser provides an on-device Translator API. No new network requests beyond the one-time model download.',
19+
options_translation_status_no_api:
20+
"Your browser doesn't support the Translator API",
21+
},
22+
ja: {
23+
ext_description:
24+
'新しいタブをmacOSの美しいエアリアル・スクリーンセーバー動画に変えます。',
25+
video_apple_help_intro:
26+
'一部のブラウザでは Apple の sylvan.apple.com の証明書を信頼せず、動画の直接読み込みに失敗する可能性があります。2つの解決方法:',
27+
video_apple_help_option2_body_pre: '対象ブラウザで',
28+
video_apple_help_option2_body_post:
29+
'を一度開きます。セキュリティ警告が表示されたら、詳細オプションを開いて続行してください。ブラウザが信頼を記憶すれば、以降は直接接続が機能します。',
30+
options_translation_description:
31+
'ブラウザが on-device Translator API を提供している場合、英語の格言を表示言語に翻訳します。初回のモデルダウンロード以外、新たなネットワークリクエストはありません。',
32+
options_translation_status_no_api:
33+
'お使いのブラウザは Translator API 未対応です',
34+
},
35+
zh_CN: {
36+
ext_description: '将新标签页变成 macOS 的华丽航拍屏保视频。',
37+
video_apple_help_intro:
38+
'部分浏览器不一定信任苹果 sylvan.apple.com 的证书,直连视频可能失败。两种解决方案:',
39+
video_apple_help_option2_body_pre: '在目标浏览器里打开',
40+
video_apple_help_option2_body_post:
41+
'一次。如果出现安全警告,打开高级选项并继续访问。浏览器通常会记住你的信任,之后直连就没问题了。',
42+
options_translation_description:
43+
'当浏览器提供 on-device Translator API 时,把英文格言翻译成你设置的显示语言。除首次模型下载外,无任何新的网络请求。',
44+
options_translation_status_no_api: '你的浏览器不支持 Translator API',
45+
},
46+
zh_TW: {
47+
ext_description: '將新分頁變成 macOS 的華麗空拍螢幕保護影片。',
48+
video_apple_help_intro:
49+
'部分瀏覽器不一定信任蘋果 sylvan.apple.com 的憑證,直連影片可能失敗。兩種解決方案:',
50+
video_apple_help_option2_body_pre: '在目標瀏覽器裡開啟',
51+
video_apple_help_option2_body_post:
52+
'一次。如果出現安全性警告,請開啟進階選項並繼續前往。瀏覽器通常會記住你的信任,之後直連就沒問題了。',
53+
options_translation_description:
54+
'當瀏覽器提供 on-device Translator API 時,把英文格言翻譯成你設定的顯示語言。除首次模型下載外,無任何新的網路請求。',
55+
options_translation_status_no_api: '你的瀏覽器不支援 Translator API',
56+
},
57+
};
958

1059
const manifest = JSON.parse(await readFile(manifestPath, 'utf8'));
1160

@@ -14,11 +63,25 @@ const manifest = JSON.parse(await readFile(manifestPath, 'utf8'));
1463
delete manifest.background;
1564

1665
if (Array.isArray(manifest.permissions)) {
17-
manifest.permissions = manifest.permissions.filter((p) => p !== 'topSites');
66+
manifest.permissions = manifest.permissions.filter(
67+
(p) => !['topSites', 'favicon'].includes(p),
68+
);
1869
if (manifest.permissions.length === 0) {
1970
delete manifest.permissions;
2071
}
2172
}
2273

2374
await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
24-
console.log('Prepared Safari-compatible dist/manifest.json');
75+
76+
for (const [locale, overrides] of Object.entries(safariLocaleOverrides)) {
77+
const messagesPath = resolve(dist, '_locales', locale, 'messages.json');
78+
const messages = JSON.parse(await readFile(messagesPath, 'utf8'));
79+
for (const [key, message] of Object.entries(overrides)) {
80+
if (messages[key]) {
81+
messages[key].message = message;
82+
}
83+
}
84+
await writeFile(messagesPath, JSON.stringify(messages, null, 2) + '\n');
85+
}
86+
87+
console.log('Prepared Safari-compatible dist assets');

src/_locales/en/messages.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"message": "Macify - Gorgeous Aerial Videos as Your New Tab"
44
},
55
"ext_description": {
6-
"message": "Transform your new tab into macOS's gorgeous aerial screensaver videos."
6+
"message": "Transform Chrome's new tab into macOS's gorgeous aerial screensaver videos."
77
},
88
"options_title": {
99
"message": "Macify Settings"
@@ -228,7 +228,7 @@
228228
"message": "Why might Apple's server need extra setup?"
229229
},
230230
"video_apple_help_intro": {
231-
"message": "Some browsers may not trust Apple's sylvan.apple.com certificate, so direct video loading can fail. Two ways to make it work:"
231+
"message": "Chrome doesn't always trust Apple's sylvan.apple.com certificate, so direct video loading may fail. Two ways to make it work:"
232232
},
233233
"video_apple_help_option1_title": {
234234
"message": "Option 1 — Use the reverse proxy (easy)"
@@ -243,7 +243,7 @@
243243
"message": "Open"
244244
},
245245
"video_apple_help_option2_body_post": {
246-
"message": "in the target browser once. If you see a security warning, open the advanced option and proceed. The browser should remember your trust after that."
246+
"message": "in Chrome once. You'll see a security warning — click Advanced, then \"Proceed to sylvan.apple.com (unsafe)\". Chrome remembers your trust and direct connection works from then on."
247247
},
248248
"video_local_help_title": {
249249
"message": "Set up a local Apache server (one-time)"
@@ -282,7 +282,7 @@
282282
"message": "Translation"
283283
},
284284
"options_translation_description": {
285-
"message": "Translates English mottos into your display language when the browser provides an on-device Translator API. No new network requests beyond the one-time model download."
285+
"message": "Translates English mottos into your display language using Chrome's built-in on-device Translator API. No new network requests beyond the one-time model download."
286286
},
287287
"options_translation_model_label": {
288288
"message": "Model"
@@ -306,7 +306,7 @@
306306
"message": "Not supported for this language pair"
307307
},
308308
"options_translation_status_no_api": {
309-
"message": "Your browser doesn't support the Translator API"
309+
"message": "Your browser doesn't support the Translator API (requires Chrome 138+)"
310310
},
311311
"options_translation_download_button": {
312312
"message": "Download model now"

src/_locales/ja/messages.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"message": "Macify - 華麗なエアリアル動画の新しいタブ"
44
},
55
"ext_description": {
6-
"message": "新しいタブをmacOSの美しいエアリアル・スクリーンセーバー動画に変えます。"
6+
"message": "Chromeの新しいタブをmacOSの美しいエアリアル・スクリーンセーバー動画に変えます。"
77
},
88
"options_title": {
99
"message": "Macify 設定"
@@ -228,7 +228,7 @@
228228
"message": "Apple のサーバーで追加設定が必要な理由"
229229
},
230230
"video_apple_help_intro": {
231-
"message": "一部のブラウザでは Apple の sylvan.apple.com の証明書を信頼せず、動画の直接読み込みに失敗する可能性があります。2つの解決方法:"
231+
"message": "Chrome が Apple の sylvan.apple.com の証明書を信頼しないことがあり、動画の直接読み込みに失敗する可能性があります。2つの解決方法:"
232232
},
233233
"video_apple_help_option1_title": {
234234
"message": "方法 1 — リバースプロキシを使う(簡単)"
@@ -240,10 +240,10 @@
240240
"message": "方法 2 — Apple の証明書を手動で信頼する(最もクリーン)"
241241
},
242242
"video_apple_help_option2_body_pre": {
243-
"message": "対象ブラウザで"
243+
"message": "Chrome で"
244244
},
245245
"video_apple_help_option2_body_post": {
246-
"message": "を一度開きます。セキュリティ警告が表示されたら、詳細オプションを開いて続行してください。ブラウザが信頼を記憶すれば、以降は直接接続が機能します。"
246+
"message": "を一度開きます。セキュリティ警告が表示されたら、「詳細」→「sylvan.apple.com にアクセスする (安全ではありません)」をクリック。Chrome が信頼を記憶し、以降は直接接続が機能します。"
247247
},
248248
"video_local_help_title": {
249249
"message": "ローカル Apache サーバーを設定する(一回だけ)"
@@ -282,7 +282,7 @@
282282
"message": "翻訳"
283283
},
284284
"options_translation_description": {
285-
"message": "ブラウザが on-device Translator API を提供している場合、英語の格言を表示言語に翻訳します。初回のモデルダウンロード以外、新たなネットワークリクエストはありません。"
285+
"message": "Chrome 内蔵の on-device Translator API を使い、英語の格言を表示言語に翻訳します。初回のモデルダウンロード以外、新たなネットワークリクエストはありません。"
286286
},
287287
"options_translation_model_label": {
288288
"message": "モデル"
@@ -306,7 +306,7 @@
306306
"message": "この言語ペアは未対応"
307307
},
308308
"options_translation_status_no_api": {
309-
"message": "お使いのブラウザは Translator API 未対応です"
309+
"message": "お使いのブラウザは Translator API 未対応です(Chrome 138+ が必要)"
310310
},
311311
"options_translation_download_button": {
312312
"message": "モデルをダウンロード"

src/_locales/zh_CN/messages.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"message": "Macify - 华丽的航拍视频新标签页"
44
},
55
"ext_description": {
6-
"message": "将新标签页变成 macOS 的华丽航拍屏保视频。"
6+
"message": "将 Chrome 的新标签页变成 macOS 的华丽航拍屏保视频。"
77
},
88
"options_title": {
99
"message": "Macify 设置"
@@ -228,7 +228,7 @@
228228
"message": "为什么苹果服务器可能需要额外配置?"
229229
},
230230
"video_apple_help_intro": {
231-
"message": "部分浏览器不一定信任苹果 sylvan.apple.com 的证书,直连视频可能失败。两种解决方案:"
231+
"message": "Chrome 不一定信任苹果 sylvan.apple.com 的证书,直连视频可能失败。两种解决方案:"
232232
},
233233
"video_apple_help_option1_title": {
234234
"message": "方案 1 — 启用反向代理(简单)"
@@ -240,10 +240,10 @@
240240
"message": "方案 2 — 手动信任苹果证书(最干净)"
241241
},
242242
"video_apple_help_option2_body_pre": {
243-
"message": "在目标浏览器里打开"
243+
"message": "在 Chrome 里打开"
244244
},
245245
"video_apple_help_option2_body_post": {
246-
"message": "一次。如果出现安全警告,打开高级选项并继续访问。浏览器通常会记住你的信任,之后直连就没问题了。"
246+
"message": "一次。会出现安全警告——点「高级」,然后点「继续访问 sylvan.apple.com(不安全)」。Chrome 会记住你的信任,之后直连就没问题了。"
247247
},
248248
"video_local_help_title": {
249249
"message": "搭建本地 Apache 服务器(一次性配置)"
@@ -282,7 +282,7 @@
282282
"message": "翻译"
283283
},
284284
"options_translation_description": {
285-
"message": "当浏览器提供 on-device Translator API 时,把英文格言翻译成你设置的显示语言。除首次模型下载外,无任何新的网络请求。"
285+
"message": "使用 Chrome 内建的 on-device Translator API 把英文格言翻译成你设置的显示语言。除首次模型下载外,无任何新的网络请求。"
286286
},
287287
"options_translation_model_label": {
288288
"message": "模型"
@@ -306,7 +306,7 @@
306306
"message": "此语言对不支持"
307307
},
308308
"options_translation_status_no_api": {
309-
"message": "你的浏览器不支持 Translator API"
309+
"message": "你的浏览器不支持 Translator API(需要 Chrome 138+)"
310310
},
311311
"options_translation_download_button": {
312312
"message": "下载模型"

0 commit comments

Comments
 (0)