Skip to content

Commit 78a419c

Browse files
rezbytearmhub
andcommitted
Use the correct website URL according to stage, closes #7941
Also replaces the website URL in faq entries according to client stage Co-authored-by: Jat Co-authored-by: armhub <[email protected]>
1 parent 687b2ae commit 78a419c

40 files changed

+197
-123
lines changed

buildSrc/DevBuild.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export async function runDevBuild({ stage, host, desktop, clean, ignoreMigration
6969
u2fAppId: `${protocol}//${hostname}:${port}/u2f-appid.json`,
7070
giftCardBaseUrl: `${protocol}//${hostname}:${port}/giftcard`,
7171
referralBaseUrl: `${protocol}//${hostname}:${port}/signup`,
72-
websiteBaseUrl: "https://tuta.com",
72+
websiteBaseUrl: domainConfigs[hostname].websiteBaseUrl ?? "https://tuta.com",
7373
},
7474
}
7575
}
@@ -223,7 +223,7 @@ globalThis.buildOptions.sqliteNativePath = "./better-sqlite3.node";`,
223223
const __dirname = path.dirname(fileURLToPath(import.meta.url))
224224
const root = __dirname.split(path.sep).slice(0, -1).join(path.sep)
225225

226-
async function createBootstrap(env, buildDir) {
226+
async function createBootstrap(env, buildDir, stage) {
227227
let jsFileName
228228
let htmlFileName
229229
switch (env.mode) {
@@ -249,7 +249,7 @@ if (env.staticUrl == null && window.tutaoDefaultApiUrl) {
249249
}
250250
import('./app.js')`
251251
await writeFile(`./${buildDir}/${jsFileName}`, template)
252-
const html = await LaunchHtml.renderHtml(imports, env)
252+
const html = await LaunchHtml.renderHtml(imports, env, stage)
253253
await writeFile(`./${buildDir}/${htmlFileName}`, html)
254254
}
255255

@@ -297,6 +297,6 @@ export async function prepareAssets(stage, host, version, domainConfigs, buildDi
297297
/** @type {EnvMode[]} */
298298
const modes = ["Browser", "App", "Desktop"]
299299
for (const mode of modes) {
300-
await createBootstrap(env.create({ staticUrl: getStaticUrl(stage, mode, host), version, mode, dist: false, domainConfigs }), buildDir)
300+
await createBootstrap(env.create({ staticUrl: getStaticUrl(stage, mode, host), version, mode, dist: false, domainConfigs }), buildDir, stage)
301301
}
302302
}

buildSrc/LaunchHtml.js

+17-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,23 @@ function getCspUrls(env) {
2121
}
2222
}
2323

24+
function getWebsiteUrl(stage) {
25+
switch (stage) {
26+
case "test":
27+
return "https://test.tuta.com"
28+
case "local":
29+
return "https://local.tuta.com:9000"
30+
default: // prod and host
31+
return "https://tuta.com"
32+
}
33+
}
34+
2435
/**
2536
* Renders the initial HTML page to bootstrap Tutanota for different environments
2637
*/
27-
export async function renderHtml(scripts, env) {
38+
export async function renderHtml(scripts, env, stage) {
39+
// ideally check if it is possible to use the website url from the env.domainConfigs here instead of getWebsiteURL()
40+
const websiteUrl = getWebsiteUrl(stage)
2841
return `<!DOCTYPE html>
2942
<html>
3043
<head>
@@ -45,19 +58,19 @@ export async function renderHtml(scripts, env) {
4558
<meta name="twitter:card" content="summary_large_image">
4659
<meta name="twitter:site" content="@TutaPrivacy">
4760
<meta name="twitter:domain" content="tuta.com">
48-
<meta name="twitter:image" content="https://tuta.com/resources/images/share-tutanota-twitter-thumbnail.png">
61+
<meta name="twitter:image" content="${websiteUrl}/resources/images/share-tutanota-twitter-thumbnail.png">
4962
<meta property="og:type" content="website">
5063
<meta property="og:site_name" content="Tuta Mail">
5164
<meta property="og:title" content="Turn ON Privacy">
5265
<meta property="og:description"
5366
content="Get a free email account with quantum-safe encryption and best privacy on all your devices. Green, secure &amp; no ads!">
5467
<meta property="og:locale" content="en">
5568
<meta property="og:url" content="https://tuta.com/">
56-
<meta property="og:image" content="https://tuta.com/resources/images/share-tutanota-fb-thumbnail.png">
69+
<meta property="og:image" content="${websiteUrl}/resources/images/share-tutanota-fb-thumbnail.png">
5770
<meta property="article:publisher" content="https://www.facebook.com/tutanota">
5871
<meta itemprop="name" content="Turn ON Privacy">
5972
<meta itemprop="description" content="Get a free email account with quantum-safe encryption and best privacy on all your devices. Green, secure &amp; no ads!">
60-
<meta itemprop="image" content="https://tuta.com/images/share_image.png">
73+
<meta itemprop="image" content="${websiteUrl}/images/share_image.png">
6174
<meta name="apple-itunes-app" content="app-id=id922429609, affiliate-data=10lSfb">
6275
</head>
6376
<body style="background-color:transparent">

buildSrc/buildWebapp.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,11 @@ self.onmessage = function (msg) {
177177
dist: true,
178178
domainConfigs,
179179
}),
180+
stage,
180181
app,
181182
)
182183
if (stage !== "release") {
183-
await createHtml(env.create({ staticUrl: restUrl, version, mode: "App", dist: true, domainConfigs }), app)
184+
await createHtml(env.create({ staticUrl: restUrl, version, mode: "App", dist: true, domainConfigs }), stage, app)
184185
}
185186

186187
await bundleServiceWorker(chunks, version, minify, buildDir)

buildSrc/createHtml.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ import path from "node:path"
1414
* staticUrl: String defining app base url for non-production environments and the native clients.
1515
* versionNumber: String containing the app's version number
1616
* @param app App to be built, defaults to mail app {String}
17+
* @param stage Deployment for which to build: 'prod' will build for the production system, 'test' for the test system, 'local' will use local.
1718
* @returns {Promise<Awaited<void>[]>}
1819
*/
19-
export async function createHtml(env, app = "mail") {
20+
export async function createHtml(env, stage, app = "mail") {
2021
let jsFileName
2122
let htmlFileName
2223
const buildDir = app === "calendar" ? "build-calendar-app" : "build"
@@ -44,7 +45,7 @@ window.env = ${JSON.stringify(env, null, 2)}
4445
${indexTemplate}`
4546
return Promise.all([
4647
_writeFile(`./${buildDir}/${jsFileName}`, index),
47-
renderHtml(imports, env).then((content) => _writeFile(`./${buildDir}/${htmlFileName}`, content)),
48+
renderHtml(imports, env, stage).then((content) => _writeFile(`./${buildDir}/${htmlFileName}`, content)),
4849
])
4950
}
5051

desktop.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
112112
}
113113

114114
if (stage === "release") {
115-
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }))
115+
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
116116
await buildDesktop(desktopBaseOpts)
117117
if (!customDesktopRelease) {
118118
const updateUrl = new URL(tutaTestUrl)
@@ -124,7 +124,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
124124
// Do not notarize test build
125125
notarize: false,
126126
})
127-
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }))
127+
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
128128
await buildDesktop(desktopTestOpts)
129129
}
130130
} else if (stage === "local") {
@@ -140,7 +140,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
140140
nameSuffix: "-snapshot",
141141
notarize: false,
142142
})
143-
await createHtml(env.create({ staticUrl: `http://${addr}:9000`, version, mode: "Desktop", dist: true, domainConfigs }))
143+
await createHtml(env.create({ staticUrl: `http://${addr}:9000`, version, mode: "Desktop", dist: true, domainConfigs }), stage)
144144
await buildDesktop(desktopLocalOpts)
145145
} else if (stage === "test") {
146146
const updateUrl = new URL(tutaTestUrl)
@@ -150,15 +150,15 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
150150
nameSuffix: "-test",
151151
notarize: false,
152152
})
153-
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }))
153+
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
154154
await buildDesktop(desktopTestOpts)
155155
} else if (stage === "prod") {
156156
const desktopProdOpts = Object.assign({}, desktopBaseOpts, {
157157
version,
158158
updateUrl: "http://localhost:9000/desktop",
159159
notarize: false,
160160
})
161-
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }))
161+
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
162162
await buildDesktop(desktopProdOpts)
163163
} else {
164164
// stage = host
@@ -168,7 +168,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
168168
nameSuffix: "-snapshot",
169169
notarize: false,
170170
})
171-
await createHtml(env.create({ staticUrl: host, version, mode: "Desktop", dist: true, domainConfigs }))
171+
await createHtml(env.create({ staticUrl: host, version, mode: "Desktop", dist: true, domainConfigs }), stage)
172172
await buildDesktop(desktopHostOpts)
173173
}
174174
}

src/calendar-app/calendar-app.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { client } from "../common/misc/ClientDetector.js"
22
import m from "mithril"
33
import Mithril, { Children, ClassComponent, Component, RouteDefs, RouteResolver, Vnode, VnodeDOM } from "mithril"
4-
import { lang, languageCodeToTag, languages } from "../common/misc/LanguageViewModel.js"
4+
import { lang, languageCodeToTag, languages, setInfoLinks } from "../common/misc/LanguageViewModel.js"
55
import { root } from "../RootView.js"
66
import { disableErrorHandlingDuringLogout, handleUncaughtError } from "../common/misc/ErrorHandler.js"
77
import { assertMainOrNodeBoot, bootFinished, isApp, isDesktop, isOfflineStorageAvailable } from "../common/api/common/Env.js"
@@ -397,6 +397,8 @@ import("../mail-app/translations/en.js")
397397
const serviceworker = await import("../common/serviceworker/ServiceWorkerClient.js")
398398
serviceworker.init(domainConfig)
399399

400+
setInfoLinks(domainConfig.websiteBaseUrl)
401+
400402
printJobsMessage(domainConfig)
401403
})
402404

src/common/gui/RenderLoginInfoLinks.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import m, { Children } from "mithril"
22
import { isApp, isDesktop } from "../api/common/Env.js"
33
import { ExternalLink } from "./base/ExternalLink.js"
4-
import { InfoLink, lang } from "../misc/LanguageViewModel.js"
4+
import { InfoLinks, lang } from "../misc/LanguageViewModel.js"
55
import { createDropdown } from "./base/Dropdown.js"
66
import { mapNullable } from "@tutao/tutanota-utils"
77
import { getWhitelabelCustomizations } from "../misc/WhitelabelCustomizations.js"
@@ -48,11 +48,11 @@ export function renderInfoLinks(): Children {
4848
}
4949

5050
function getImprintLink(): string | null {
51-
return mapNullable(getWhitelabelCustomizations(window), (c) => c.imprintUrl) || InfoLink.About
51+
return mapNullable(getWhitelabelCustomizations(window), (c) => c.imprintUrl) || InfoLinks.About
5252
}
5353

5454
function getPrivacyStatementLink(): string | null {
55-
return mapNullable(getWhitelabelCustomizations(window), (c) => c.privacyStatementUrl) || InfoLink.Privacy
55+
return mapNullable(getWhitelabelCustomizations(window), (c) => c.privacyStatementUrl) || InfoLinks.Privacy
5656
}
5757

5858
/**

src/common/login/recover/TakeOverDeletedAddressDialog.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import stream from "mithril/stream"
33
import { AccessBlockedError, AccessDeactivatedError, InvalidDataError, NotAuthenticatedError, TooManyRequestsError } from "../../api/common/error/RestError"
44
import { showProgressDialog } from "../../gui/dialogs/ProgressDialog"
55
import { isMailAddress } from "../../misc/FormatValidator.js"
6-
import { InfoLink, lang } from "../../misc/LanguageViewModel.js"
6+
import { InfoLinks, lang } from "../../misc/LanguageViewModel.js"
77
import { Autocomplete, TextField, TextFieldType } from "../../gui/base/TextField.js"
88
import { Dialog, DialogType } from "../../gui/base/Dialog"
99
import { HtmlEditor, HtmlEditorMode } from "../../gui/editor/HtmlEditor"
@@ -27,7 +27,7 @@ export function showTakeOverDialog(mailAddress: string, password: string): Dialo
2727
view: () => {
2828
return [
2929
m(".mt", lang.get("takeOverUnusedAddress_msg")),
30-
m(MoreInfoLink, { link: InfoLink.InactiveAccounts }),
30+
m(MoreInfoLink, { link: InfoLinks.InactiveAccounts }),
3131
m(TextField, {
3232
label: "targetAddress_label",
3333
value: targetAccountAddress(),

src/common/misc/LanguageViewModel.ts

+62-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { lazy } from "@tutao/tutanota-utils"
2-
import { downcast, typedEntries } from "@tutao/tutanota-utils"
1+
import { downcast, lazy, typedEntries } from "@tutao/tutanota-utils"
32
import type { TranslationKeyType } from "./TranslationKey"
43
import { getWhitelabelCustomizations, WhitelabelCustomizations } from "./WhitelabelCustomizations"
54
import { assertMainOrNodeBoot } from "../api/common/Env"
@@ -194,34 +193,69 @@ export const languageNative: ReadonlyArray<{
194193
}
195194
})
196195

197-
export const enum InfoLink {
198-
HomePage = "https://tuta.com",
199-
About = "https://tuta.com/imprint",
196+
// Modifiable so `app.js` can initialize it to the website urls in the domain config
197+
export let InfoLinks = {
198+
HomePage: "https://tuta.com",
199+
About: `https://tuta.com/imprint`,
200200
//terms
201-
Terms = "https://tuta.com/terms",
202-
Privacy = "https://tuta.com/privacy-policy",
203-
GiftCardsTerms = "https://tuta.com/giftCardsTerms",
201+
Terms: `https://tuta.com/terms`,
202+
Privacy: `https://tuta.com/privacy-policy`,
203+
GiftCardsTerms: `https://tuta.com/giftCardsTerms`,
204204
//faq
205-
RecoverCode = "https://tuta.com/faq#reset",
206-
SecondFactor = "https://tuta.com/faq#2fa",
207-
SpamRules = "https://tuta.com/faq#spam",
208-
DomainInfo = "https://tuta.com/faq#custom-domain",
209-
Whitelabel = "https://tuta.com/faq#whitelabel",
210-
ReferralLink = "https://tuta.com/faq#refer-a-friend",
211-
Webview = "https://tuta.com/faq#webview",
212-
Phishing = "https://tuta.com/faq#phishing",
213-
MailAuth = "https://tuta.com/faq#mail-auth",
214-
RunInBackground = "https://tuta.com/faq#tray-desktop",
215-
LoadImages = "https://tuta.com/faq#load-images",
216-
Usage = "https://tuta.com/faq#usage",
217-
Download = "https://tuta.com/#download",
218-
SharedMailboxes = "https://tuta.com/support/#shared-mailboxes",
219-
InactiveAccounts = "https://tuta.com/faq/#inactive-accounts",
220-
AppStorePaymentChange = "https://tuta.com/support/#appstore-payment-change",
221-
AppStorePayment = "https://tuta.com/support/#appstore-payments",
222-
AppStoreDowngrade = "https://tuta.com/support/#appstore-subscription-downgrade",
223-
PasswordGenerator = "https://tuta.com/faq#passphrase-generator",
224-
HomePageFreeSignup = "https://tuta.com/free-email",
205+
RecoverCode: `https://tuta.com/faq#reset`,
206+
SecondFactor: `https://tuta.com/faq#2fa`,
207+
SpamRules: `https://tuta.com/faq#spam`,
208+
DomainInfo: `https://tuta.com/faq#custom-domain`,
209+
Whitelabel: `https://tuta.com/faq#whitelabel`,
210+
ReferralLink: `https://tuta.com/faq#refer-a-friend`,
211+
Webview: `https://tuta.com/faq#webview`,
212+
Phishing: `https://tuta.com/faq#phishing`,
213+
MailAuth: `https://tuta.com/faq#mail-auth`,
214+
RunInBackground: `https://tuta.com/faq#tray-desktop`,
215+
LoadImages: `https://tuta.com/faq#load-images`,
216+
Usage: `https://tuta.com/faq#usage`,
217+
Download: `https://tuta.com/#download`,
218+
SharedMailboxes: `https://tuta.com/support/#shared-mailboxes`,
219+
InactiveAccounts: `https://tuta.com/faq/#inactive-accounts`,
220+
AppStorePaymentChange: `https://tuta.com/support/#appstore-payment-change`,
221+
AppStorePayment: `https://tuta.com/support/#appstore-payments`,
222+
AppStoreDowngrade: `https://tuta.com/support/#appstore-subscription-downgrade`,
223+
PasswordGenerator: `https://tuta.com/faq#passphrase-generator`,
224+
HomePageFreeSignup: `https://tuta.com/free-email`,
225+
}
226+
export type InfoLink = (typeof InfoLinks)[keyof typeof InfoLinks]
227+
228+
// Updates the website links in `InfoLinks` to use `websiteUrl` as the root
229+
export function setInfoLinks(websiteUrl: string) {
230+
InfoLinks = {
231+
HomePage: websiteUrl,
232+
About: `${websiteUrl}/imprint`,
233+
//terms
234+
Terms: `${websiteUrl}/terms`,
235+
Privacy: `${websiteUrl}/privacy-policy`,
236+
GiftCardsTerms: `${websiteUrl}/giftCardsTerms`,
237+
//faq
238+
RecoverCode: `${websiteUrl}/faq#reset`,
239+
SecondFactor: `${websiteUrl}/faq#2fa`,
240+
SpamRules: `${websiteUrl}/faq#spam`,
241+
DomainInfo: `${websiteUrl}/faq#custom-domain`,
242+
Whitelabel: `${websiteUrl}/faq#whitelabel`,
243+
ReferralLink: `${websiteUrl}/faq#refer-a-friend`,
244+
Webview: `${websiteUrl}/faq#webview`,
245+
Phishing: `${websiteUrl}/faq#phishing`,
246+
MailAuth: `${websiteUrl}/faq#mail-auth`,
247+
RunInBackground: `${websiteUrl}/faq#tray-desktop`,
248+
LoadImages: `${websiteUrl}/faq#load-images`,
249+
Usage: `${websiteUrl}/faq#usage`,
250+
Download: `${websiteUrl}/#download`,
251+
SharedMailboxes: `${websiteUrl}/support/#shared-mailboxes`,
252+
InactiveAccounts: `${websiteUrl}/faq/#inactive-accounts`,
253+
AppStorePaymentChange: `${websiteUrl}/support/#appstore-payment-change`,
254+
AppStorePayment: `${websiteUrl}/support/#appstore-payments`,
255+
AppStoreDowngrade: `${websiteUrl}/support/#appstore-subscription-downgrade`,
256+
PasswordGenerator: `${websiteUrl}/faq#passphrase-generator`,
257+
HomePageFreeSignup: `${websiteUrl}/free-email`,
258+
}
225259
}
226260

227261
/**

src/common/misc/news/MoreInfoLink.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { InfoLink, lang } from "../LanguageViewModel.js"
1+
import { InfoLink, InfoLinks, lang } from "../LanguageViewModel.js"
22
import m, { Children, Component, Vnode } from "mithril"
33
import { ExternalLink, relDocument } from "../../gui/base/ExternalLink.js"
44

@@ -15,17 +15,17 @@ export class MoreInfoLink implements Component<MoreInfoLinkAttrs> {
1515
view(vnode: Vnode<MoreInfoLinkAttrs>): Children {
1616
let specialType: relDocument | undefined
1717
switch (vnode.attrs.link) {
18-
case InfoLink.HomePage:
18+
case InfoLinks.HomePage:
1919
specialType = "me"
2020
break
21-
case InfoLink.About:
21+
case InfoLinks.About:
2222
specialType = "license"
2323
break
24-
case InfoLink.Privacy:
24+
case InfoLinks.Privacy:
2525
specialType = "privacy-policy"
2626
break
27-
case InfoLink.Terms:
28-
case InfoLink.GiftCardsTerms:
27+
case InfoLinks.Terms:
28+
case InfoLinks.GiftCardsTerms:
2929
specialType = "terms-of-service"
3030
break
3131
default:

src/common/misc/news/items/NewPlansNews.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NewsListItem } from "../NewsListItem.js"
22
import m, { Children } from "mithril"
33
import { NewsId } from "../../../api/entities/tutanota/TypeRefs.js"
4-
import { InfoLink, lang } from "../../LanguageViewModel.js"
4+
import { InfoLinks, lang } from "../../LanguageViewModel.js"
55
import { Button, ButtonAttrs, ButtonType } from "../../../gui/base/Button.js"
66
import { NewsModel } from "../NewsModel.js"
77
import { UserController } from "../../../api/main/UserController.js"
@@ -23,7 +23,7 @@ export class NewPlansNews implements NewsListItem {
2323
}
2424

2525
render(newsId: NewsId): Children {
26-
const lnk = InfoLink.Privacy
26+
const lnk = InfoLinks.Privacy
2727

2828
const acknowledgeAction = () => {
2929
this.newsModel.acknowledgeNews(newsId.newsItemId).then(m.redraw)

src/common/misc/news/items/NewPlansOfferEndingNews.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NewsListItem } from "../NewsListItem.js"
22
import m, { Children } from "mithril"
33
import { NewsId } from "../../../api/entities/tutanota/TypeRefs.js"
4-
import { InfoLink, lang } from "../../LanguageViewModel.js"
4+
import { lang } from "../../LanguageViewModel.js"
55
import { Button, ButtonAttrs, ButtonType } from "../../../gui/base/Button.js"
66
import { NewsModel } from "../NewsModel.js"
77
import { UserController } from "../../../api/main/UserController.js"

0 commit comments

Comments
 (0)