Skip to content

Commit

Permalink
Use the correct website URL according to stage, closes #7941
Browse files Browse the repository at this point in the history
Also replaces the website URL in faq entries according to client stage

Co-authored-by: Jat
Co-authored-by: armhub <armhub@users.noreply.github.com>
  • Loading branch information
rezbyte and armhub committed Dec 20, 2024
1 parent 687b2ae commit 78a419c
Show file tree
Hide file tree
Showing 40 changed files with 197 additions and 123 deletions.
8 changes: 4 additions & 4 deletions buildSrc/DevBuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export async function runDevBuild({ stage, host, desktop, clean, ignoreMigration
u2fAppId: `${protocol}//${hostname}:${port}/u2f-appid.json`,
giftCardBaseUrl: `${protocol}//${hostname}:${port}/giftcard`,
referralBaseUrl: `${protocol}//${hostname}:${port}/signup`,
websiteBaseUrl: "https://tuta.com",
websiteBaseUrl: domainConfigs[hostname].websiteBaseUrl ?? "https://tuta.com",
},
}
}
Expand Down Expand Up @@ -223,7 +223,7 @@ globalThis.buildOptions.sqliteNativePath = "./better-sqlite3.node";`,
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const root = __dirname.split(path.sep).slice(0, -1).join(path.sep)

async function createBootstrap(env, buildDir) {
async function createBootstrap(env, buildDir, stage) {
let jsFileName
let htmlFileName
switch (env.mode) {
Expand All @@ -249,7 +249,7 @@ if (env.staticUrl == null && window.tutaoDefaultApiUrl) {
}
import('./app.js')`
await writeFile(`./${buildDir}/${jsFileName}`, template)
const html = await LaunchHtml.renderHtml(imports, env)
const html = await LaunchHtml.renderHtml(imports, env, stage)
await writeFile(`./${buildDir}/${htmlFileName}`, html)
}

Expand Down Expand Up @@ -297,6 +297,6 @@ export async function prepareAssets(stage, host, version, domainConfigs, buildDi
/** @type {EnvMode[]} */
const modes = ["Browser", "App", "Desktop"]
for (const mode of modes) {
await createBootstrap(env.create({ staticUrl: getStaticUrl(stage, mode, host), version, mode, dist: false, domainConfigs }), buildDir)
await createBootstrap(env.create({ staticUrl: getStaticUrl(stage, mode, host), version, mode, dist: false, domainConfigs }), buildDir, stage)
}
}
21 changes: 17 additions & 4 deletions buildSrc/LaunchHtml.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,23 @@ function getCspUrls(env) {
}
}

function getWebsiteUrl(stage) {
switch (stage) {
case "test":
return "https://test.tuta.com"
case "local":
return "https://local.tuta.com:9000"
default: // prod and host
return "https://tuta.com"
}
}

/**
* Renders the initial HTML page to bootstrap Tutanota for different environments
*/
export async function renderHtml(scripts, env) {
export async function renderHtml(scripts, env, stage) {
// ideally check if it is possible to use the website url from the env.domainConfigs here instead of getWebsiteURL()
const websiteUrl = getWebsiteUrl(stage)
return `<!DOCTYPE html>
<html>
<head>
Expand All @@ -45,19 +58,19 @@ export async function renderHtml(scripts, env) {
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@TutaPrivacy">
<meta name="twitter:domain" content="tuta.com">
<meta name="twitter:image" content="https://tuta.com/resources/images/share-tutanota-twitter-thumbnail.png">
<meta name="twitter:image" content="${websiteUrl}/resources/images/share-tutanota-twitter-thumbnail.png">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Tuta Mail">
<meta property="og:title" content="Turn ON Privacy">
<meta property="og:description"
content="Get a free email account with quantum-safe encryption and best privacy on all your devices. Green, secure &amp; no ads!">
<meta property="og:locale" content="en">
<meta property="og:url" content="https://tuta.com/">
<meta property="og:image" content="https://tuta.com/resources/images/share-tutanota-fb-thumbnail.png">
<meta property="og:image" content="${websiteUrl}/resources/images/share-tutanota-fb-thumbnail.png">
<meta property="article:publisher" content="https://www.facebook.com/tutanota">
<meta itemprop="name" content="Turn ON Privacy">
<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!">
<meta itemprop="image" content="https://tuta.com/images/share_image.png">
<meta itemprop="image" content="${websiteUrl}/images/share_image.png">
<meta name="apple-itunes-app" content="app-id=id922429609, affiliate-data=10lSfb">
</head>
<body style="background-color:transparent">
Expand Down
3 changes: 2 additions & 1 deletion buildSrc/buildWebapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,11 @@ self.onmessage = function (msg) {
dist: true,
domainConfigs,
}),
stage,
app,
)
if (stage !== "release") {
await createHtml(env.create({ staticUrl: restUrl, version, mode: "App", dist: true, domainConfigs }), app)
await createHtml(env.create({ staticUrl: restUrl, version, mode: "App", dist: true, domainConfigs }), stage, app)
}

await bundleServiceWorker(chunks, version, minify, buildDir)
Expand Down
5 changes: 3 additions & 2 deletions buildSrc/createHtml.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import path from "node:path"
* staticUrl: String defining app base url for non-production environments and the native clients.
* versionNumber: String containing the app's version number
* @param app App to be built, defaults to mail app {String}
* @param stage Deployment for which to build: 'prod' will build for the production system, 'test' for the test system, 'local' will use local.
* @returns {Promise<Awaited<void>[]>}
*/
export async function createHtml(env, app = "mail") {
export async function createHtml(env, stage, app = "mail") {
let jsFileName
let htmlFileName
const buildDir = app === "calendar" ? "build-calendar-app" : "build"
Expand Down Expand Up @@ -44,7 +45,7 @@ window.env = ${JSON.stringify(env, null, 2)}
${indexTemplate}`
return Promise.all([
_writeFile(`./${buildDir}/${jsFileName}`, index),
renderHtml(imports, env).then((content) => _writeFile(`./${buildDir}/${htmlFileName}`, content)),
renderHtml(imports, env, stage).then((content) => _writeFile(`./${buildDir}/${htmlFileName}`, content)),
])
}

Expand Down
12 changes: 6 additions & 6 deletions desktop.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
}

if (stage === "release") {
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }))
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
await buildDesktop(desktopBaseOpts)
if (!customDesktopRelease) {
const updateUrl = new URL(tutaTestUrl)
Expand All @@ -124,7 +124,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
// Do not notarize test build
notarize: false,
})
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }))
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
await buildDesktop(desktopTestOpts)
}
} else if (stage === "local") {
Expand All @@ -140,7 +140,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
nameSuffix: "-snapshot",
notarize: false,
})
await createHtml(env.create({ staticUrl: `http://${addr}:9000`, version, mode: "Desktop", dist: true, domainConfigs }))
await createHtml(env.create({ staticUrl: `http://${addr}:9000`, version, mode: "Desktop", dist: true, domainConfigs }), stage)
await buildDesktop(desktopLocalOpts)
} else if (stage === "test") {
const updateUrl = new URL(tutaTestUrl)
Expand All @@ -150,15 +150,15 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
nameSuffix: "-test",
notarize: false,
})
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }))
await createHtml(env.create({ staticUrl: tutaTestUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
await buildDesktop(desktopTestOpts)
} else if (stage === "prod") {
const desktopProdOpts = Object.assign({}, desktopBaseOpts, {
version,
updateUrl: "http://localhost:9000/desktop",
notarize: false,
})
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }))
await createHtml(env.create({ staticUrl: tutaAppUrl, version, mode: "Desktop", dist: true, domainConfigs }), stage)
await buildDesktop(desktopProdOpts)
} else {
// stage = host
Expand All @@ -168,7 +168,7 @@ async function buildDesktopClient(version, { stage, host, platform, architecture
nameSuffix: "-snapshot",
notarize: false,
})
await createHtml(env.create({ staticUrl: host, version, mode: "Desktop", dist: true, domainConfigs }))
await createHtml(env.create({ staticUrl: host, version, mode: "Desktop", dist: true, domainConfigs }), stage)
await buildDesktop(desktopHostOpts)
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/calendar-app/calendar-app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { client } from "../common/misc/ClientDetector.js"
import m from "mithril"
import Mithril, { Children, ClassComponent, Component, RouteDefs, RouteResolver, Vnode, VnodeDOM } from "mithril"
import { lang, languageCodeToTag, languages } from "../common/misc/LanguageViewModel.js"
import { lang, languageCodeToTag, languages, setInfoLinks } from "../common/misc/LanguageViewModel.js"
import { root } from "../RootView.js"
import { disableErrorHandlingDuringLogout, handleUncaughtError } from "../common/misc/ErrorHandler.js"
import { assertMainOrNodeBoot, bootFinished, isApp, isDesktop, isOfflineStorageAvailable } from "../common/api/common/Env.js"
Expand Down Expand Up @@ -397,6 +397,8 @@ import("../mail-app/translations/en.js")
const serviceworker = await import("../common/serviceworker/ServiceWorkerClient.js")
serviceworker.init(domainConfig)

setInfoLinks(domainConfig.websiteBaseUrl)

printJobsMessage(domainConfig)
})

Expand Down
6 changes: 3 additions & 3 deletions src/common/gui/RenderLoginInfoLinks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import m, { Children } from "mithril"
import { isApp, isDesktop } from "../api/common/Env.js"
import { ExternalLink } from "./base/ExternalLink.js"
import { InfoLink, lang } from "../misc/LanguageViewModel.js"
import { InfoLinks, lang } from "../misc/LanguageViewModel.js"
import { createDropdown } from "./base/Dropdown.js"
import { mapNullable } from "@tutao/tutanota-utils"
import { getWhitelabelCustomizations } from "../misc/WhitelabelCustomizations.js"
Expand Down Expand Up @@ -48,11 +48,11 @@ export function renderInfoLinks(): Children {
}

function getImprintLink(): string | null {
return mapNullable(getWhitelabelCustomizations(window), (c) => c.imprintUrl) || InfoLink.About
return mapNullable(getWhitelabelCustomizations(window), (c) => c.imprintUrl) || InfoLinks.About
}

function getPrivacyStatementLink(): string | null {
return mapNullable(getWhitelabelCustomizations(window), (c) => c.privacyStatementUrl) || InfoLink.Privacy
return mapNullable(getWhitelabelCustomizations(window), (c) => c.privacyStatementUrl) || InfoLinks.Privacy
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/common/login/recover/TakeOverDeletedAddressDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import stream from "mithril/stream"
import { AccessBlockedError, AccessDeactivatedError, InvalidDataError, NotAuthenticatedError, TooManyRequestsError } from "../../api/common/error/RestError"
import { showProgressDialog } from "../../gui/dialogs/ProgressDialog"
import { isMailAddress } from "../../misc/FormatValidator.js"
import { InfoLink, lang } from "../../misc/LanguageViewModel.js"
import { InfoLinks, lang } from "../../misc/LanguageViewModel.js"
import { Autocomplete, TextField, TextFieldType } from "../../gui/base/TextField.js"
import { Dialog, DialogType } from "../../gui/base/Dialog"
import { HtmlEditor, HtmlEditorMode } from "../../gui/editor/HtmlEditor"
Expand All @@ -27,7 +27,7 @@ export function showTakeOverDialog(mailAddress: string, password: string): Dialo
view: () => {
return [
m(".mt", lang.get("takeOverUnusedAddress_msg")),
m(MoreInfoLink, { link: InfoLink.InactiveAccounts }),
m(MoreInfoLink, { link: InfoLinks.InactiveAccounts }),
m(TextField, {
label: "targetAddress_label",
value: targetAccountAddress(),
Expand Down
90 changes: 62 additions & 28 deletions src/common/misc/LanguageViewModel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { lazy } from "@tutao/tutanota-utils"
import { downcast, typedEntries } from "@tutao/tutanota-utils"
import { downcast, lazy, typedEntries } from "@tutao/tutanota-utils"
import type { TranslationKeyType } from "./TranslationKey"
import { getWhitelabelCustomizations, WhitelabelCustomizations } from "./WhitelabelCustomizations"
import { assertMainOrNodeBoot } from "../api/common/Env"
Expand Down Expand Up @@ -194,34 +193,69 @@ export const languageNative: ReadonlyArray<{
}
})

export const enum InfoLink {
HomePage = "https://tuta.com",
About = "https://tuta.com/imprint",
// Modifiable so `app.js` can initialize it to the website urls in the domain config
export let InfoLinks = {
HomePage: "https://tuta.com",
About: `https://tuta.com/imprint`,
//terms
Terms = "https://tuta.com/terms",
Privacy = "https://tuta.com/privacy-policy",
GiftCardsTerms = "https://tuta.com/giftCardsTerms",
Terms: `https://tuta.com/terms`,
Privacy: `https://tuta.com/privacy-policy`,
GiftCardsTerms: `https://tuta.com/giftCardsTerms`,
//faq
RecoverCode = "https://tuta.com/faq#reset",
SecondFactor = "https://tuta.com/faq#2fa",
SpamRules = "https://tuta.com/faq#spam",
DomainInfo = "https://tuta.com/faq#custom-domain",
Whitelabel = "https://tuta.com/faq#whitelabel",
ReferralLink = "https://tuta.com/faq#refer-a-friend",
Webview = "https://tuta.com/faq#webview",
Phishing = "https://tuta.com/faq#phishing",
MailAuth = "https://tuta.com/faq#mail-auth",
RunInBackground = "https://tuta.com/faq#tray-desktop",
LoadImages = "https://tuta.com/faq#load-images",
Usage = "https://tuta.com/faq#usage",
Download = "https://tuta.com/#download",
SharedMailboxes = "https://tuta.com/support/#shared-mailboxes",
InactiveAccounts = "https://tuta.com/faq/#inactive-accounts",
AppStorePaymentChange = "https://tuta.com/support/#appstore-payment-change",
AppStorePayment = "https://tuta.com/support/#appstore-payments",
AppStoreDowngrade = "https://tuta.com/support/#appstore-subscription-downgrade",
PasswordGenerator = "https://tuta.com/faq#passphrase-generator",
HomePageFreeSignup = "https://tuta.com/free-email",
RecoverCode: `https://tuta.com/faq#reset`,
SecondFactor: `https://tuta.com/faq#2fa`,
SpamRules: `https://tuta.com/faq#spam`,
DomainInfo: `https://tuta.com/faq#custom-domain`,
Whitelabel: `https://tuta.com/faq#whitelabel`,
ReferralLink: `https://tuta.com/faq#refer-a-friend`,
Webview: `https://tuta.com/faq#webview`,
Phishing: `https://tuta.com/faq#phishing`,
MailAuth: `https://tuta.com/faq#mail-auth`,
RunInBackground: `https://tuta.com/faq#tray-desktop`,
LoadImages: `https://tuta.com/faq#load-images`,
Usage: `https://tuta.com/faq#usage`,
Download: `https://tuta.com/#download`,
SharedMailboxes: `https://tuta.com/support/#shared-mailboxes`,
InactiveAccounts: `https://tuta.com/faq/#inactive-accounts`,
AppStorePaymentChange: `https://tuta.com/support/#appstore-payment-change`,
AppStorePayment: `https://tuta.com/support/#appstore-payments`,
AppStoreDowngrade: `https://tuta.com/support/#appstore-subscription-downgrade`,
PasswordGenerator: `https://tuta.com/faq#passphrase-generator`,
HomePageFreeSignup: `https://tuta.com/free-email`,
}
export type InfoLink = (typeof InfoLinks)[keyof typeof InfoLinks]

// Updates the website links in `InfoLinks` to use `websiteUrl` as the root
export function setInfoLinks(websiteUrl: string) {
InfoLinks = {
HomePage: websiteUrl,
About: `${websiteUrl}/imprint`,
//terms
Terms: `${websiteUrl}/terms`,
Privacy: `${websiteUrl}/privacy-policy`,
GiftCardsTerms: `${websiteUrl}/giftCardsTerms`,
//faq
RecoverCode: `${websiteUrl}/faq#reset`,
SecondFactor: `${websiteUrl}/faq#2fa`,
SpamRules: `${websiteUrl}/faq#spam`,
DomainInfo: `${websiteUrl}/faq#custom-domain`,
Whitelabel: `${websiteUrl}/faq#whitelabel`,
ReferralLink: `${websiteUrl}/faq#refer-a-friend`,
Webview: `${websiteUrl}/faq#webview`,
Phishing: `${websiteUrl}/faq#phishing`,
MailAuth: `${websiteUrl}/faq#mail-auth`,
RunInBackground: `${websiteUrl}/faq#tray-desktop`,
LoadImages: `${websiteUrl}/faq#load-images`,
Usage: `${websiteUrl}/faq#usage`,
Download: `${websiteUrl}/#download`,
SharedMailboxes: `${websiteUrl}/support/#shared-mailboxes`,
InactiveAccounts: `${websiteUrl}/faq/#inactive-accounts`,
AppStorePaymentChange: `${websiteUrl}/support/#appstore-payment-change`,
AppStorePayment: `${websiteUrl}/support/#appstore-payments`,
AppStoreDowngrade: `${websiteUrl}/support/#appstore-subscription-downgrade`,
PasswordGenerator: `${websiteUrl}/faq#passphrase-generator`,
HomePageFreeSignup: `${websiteUrl}/free-email`,
}
}

/**
Expand Down
12 changes: 6 additions & 6 deletions src/common/misc/news/MoreInfoLink.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InfoLink, lang } from "../LanguageViewModel.js"
import { InfoLink, InfoLinks, lang } from "../LanguageViewModel.js"
import m, { Children, Component, Vnode } from "mithril"
import { ExternalLink, relDocument } from "../../gui/base/ExternalLink.js"

Expand All @@ -15,17 +15,17 @@ export class MoreInfoLink implements Component<MoreInfoLinkAttrs> {
view(vnode: Vnode<MoreInfoLinkAttrs>): Children {
let specialType: relDocument | undefined
switch (vnode.attrs.link) {
case InfoLink.HomePage:
case InfoLinks.HomePage:
specialType = "me"
break
case InfoLink.About:
case InfoLinks.About:
specialType = "license"
break
case InfoLink.Privacy:
case InfoLinks.Privacy:
specialType = "privacy-policy"
break
case InfoLink.Terms:
case InfoLink.GiftCardsTerms:
case InfoLinks.Terms:
case InfoLinks.GiftCardsTerms:
specialType = "terms-of-service"
break
default:
Expand Down
4 changes: 2 additions & 2 deletions src/common/misc/news/items/NewPlansNews.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NewsListItem } from "../NewsListItem.js"
import m, { Children } from "mithril"
import { NewsId } from "../../../api/entities/tutanota/TypeRefs.js"
import { InfoLink, lang } from "../../LanguageViewModel.js"
import { InfoLinks, lang } from "../../LanguageViewModel.js"
import { Button, ButtonAttrs, ButtonType } from "../../../gui/base/Button.js"
import { NewsModel } from "../NewsModel.js"
import { UserController } from "../../../api/main/UserController.js"
Expand All @@ -23,7 +23,7 @@ export class NewPlansNews implements NewsListItem {
}

render(newsId: NewsId): Children {
const lnk = InfoLink.Privacy
const lnk = InfoLinks.Privacy

const acknowledgeAction = () => {
this.newsModel.acknowledgeNews(newsId.newsItemId).then(m.redraw)
Expand Down
2 changes: 1 addition & 1 deletion src/common/misc/news/items/NewPlansOfferEndingNews.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NewsListItem } from "../NewsListItem.js"
import m, { Children } from "mithril"
import { NewsId } from "../../../api/entities/tutanota/TypeRefs.js"
import { InfoLink, lang } from "../../LanguageViewModel.js"
import { lang } from "../../LanguageViewModel.js"
import { Button, ButtonAttrs, ButtonType } from "../../../gui/base/Button.js"
import { NewsModel } from "../NewsModel.js"
import { UserController } from "../../../api/main/UserController.js"
Expand Down
Loading

0 comments on commit 78a419c

Please sign in to comment.