diff --git a/Assets/WebsiteAssets/images/BadgeMacOSM1.png b/Assets/WebsiteAssets/images/BadgeMacOSM1.png new file mode 100644 index 000000000..3ce6cfee7 Binary files /dev/null and b/Assets/WebsiteAssets/images/BadgeMacOSM1.png differ diff --git a/Assets/WebsiteAssets/js/script.js b/Assets/WebsiteAssets/js/script.js index 902ca8358..f61464fbb 100644 --- a/Assets/WebsiteAssets/js/script.js +++ b/Assets/WebsiteAssets/js/script.js @@ -1,6 +1,31 @@ -function getOs() { +async function getOs() { + + // The macOS release is available for Intel and Apple silicon processors, + // and the only way to get that info is through this new + // `getHighEntropyValues` function (which is not available on all browsers). + // So here we either return "macOs" for Intel or "macOsM1" for Apple + // Silicon. If we don't know which it is, we return "macOsUndefined". + // https://stackoverflow.com/a/75177111/561309 + + if (navigator.appVersion.indexOf("Mac")!=-1) { + let platformInfo = null; + try { + platformInfo = await navigator.userAgentData.getHighEntropyValues(['architecture']) + } catch (error) { + console.warn('Failed getting Mac architecture:', error); + return 'macOsUndefined'; + } + + console.info('Got platform info:', platformInfo); + + if (platformInfo.architecture === 'arm') { + return "macOsM1"; + } else { + return "macOs"; + } + } + if (navigator.appVersion.indexOf("Win")!=-1) return "windows"; - if (navigator.appVersion.indexOf("Mac")!=-1) return "macOs"; if (navigator.appVersion.indexOf("X11")!=-1) return "linux"; if (navigator.appVersion.indexOf("Linux")!=-1) return "linux"; return null; @@ -45,7 +70,7 @@ function setupMobileMenu() { }); } -function setupDownloadPage() { +async function setupDownloadPage() { if (!$('.page-download').length) return; const downloadLinks = {}; @@ -55,6 +80,7 @@ function setupDownloadPage() { if (href.indexOf('-Setup') > 0) downloadLinks['windows'] = href; if (href.indexOf('.dmg') > 0) downloadLinks['macOs'] = href; + if (href.endsWith('arm64.DMG')) downloadLinks['macOsM1'] = href; if (href.indexOf('.AppImage') > 0) downloadLinks['linux'] = href; }); @@ -70,8 +96,17 @@ function setupDownloadPage() { if (mobileOs) { $('.page-download .intro').hide(); } else { - const os = getOs(); - if (!os || !downloadLinks[os]) { + const os = await getOs(); + + if (os === 'macOsUndefined') { + // If we don't know which macOS version it is, we let the user choose. + $('.main-content .intro').html('
The macOS release is available for Intel processors or for Apple Silicon (M1) processors. Please select your version:
'); + const macOsLink = $('.download-link-macOs'); + const macOsM1Link = $('.download-link-macOsM1'); + $('.macos-m1-info').after('To find out what processor you have, click on the Apple logo in the macOS menu bar, choose About This Mac from the dropdown menu. If you have an Apple silicon it should say"Apple M1" under "Chip". Otherwise you have an Intel processor.
'); + $('.macos-m1-info').after(macOsM1Link); + $('.macos-m1-info').after(macOsLink); + } else if (!os || !downloadLinks[os]) { // If we don't know, display the section to manually download the app $('.page-download .get-it-desktop').show(); } else if (os === 'linux') { @@ -89,5 +124,5 @@ function setupDownloadPage() { $(function () { setupMobileMenu(); - setupDownloadPage(); + void setupDownloadPage(); }); diff --git a/packages/tools/update-readme-download.ts b/packages/tools/update-readme-download.ts index a00e115b9..1d8f818c0 100644 --- a/packages/tools/update-readme-download.ts +++ b/packages/tools/update-readme-download.ts @@ -13,6 +13,7 @@ async function msleep(ms: number) { export enum OS { MacOs = 'macos', + MacOsM1 = 'macosm1', Windows = 'windows', Android = 'android', Android32 = 'android32', @@ -31,7 +32,11 @@ export const downloadUrl = (release: GitHubRelease, os: OS, portable = false) => const githubUrl = 'github.com/laurent22/joplin/releases/download/'; const joplinDomain = 'objects.joplinusercontent.com/'; - if (ext === 'dmg' && os === OS.MacOs) return asset.browser_download_url.replace(githubUrl, joplinDomain); + if (name.endsWith('arm64.DMG') && os === OS.MacOsM1) { + return asset.browser_download_url.replace(githubUrl, joplinDomain); + } else if (ext === 'dmg' && os === OS.MacOs) { + return asset.browser_download_url.replace(githubUrl, joplinDomain); + } if (ext === 'exe' && os === OS.Windows) { if (portable) { @@ -81,29 +86,28 @@ async function main(argv: any) { const androidRelease = await gitHubLatestRelease('joplin-android'); - // const android32Url = downloadUrl(androidRelease, OS.Android32); const androidUrl = downloadUrl(androidRelease, OS.Android); const winUrl = downloadUrl(release, OS.Windows); const winPortableUrl = downloadUrl(release, OS.Windows, true); const macOsUrl = downloadUrl(release, OS.MacOs); + const macOsM1Url = downloadUrl(release, OS.MacOsM1); const linuxUrl = downloadUrl(release, OS.Linux); console.info('Windows: ', winUrl); console.info('Windows Portable: ', winPortableUrl); console.info('macOS: ', macOsUrl); + console.info('macOSM1: ', macOsM1Url); console.info('Linux: ', linuxUrl); console.info('Android: ', androidUrl); - // console.info('Android 32: ', android32Url); let content = readmeContent(); if (winUrl) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/Joplin-Setup-.*?\.exe)/, winUrl); if (winPortableUrl) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/JoplinPortable.exe)/, winPortableUrl); if (macOsUrl) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/Joplin-.*?\.dmg)/, macOsUrl); + if (macOsM1Url) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/Joplin-.*?arm64\.DMG)/, macOsM1Url); if (linuxUrl) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/Joplin-.*?\.AppImage)/, linuxUrl); - if (androidUrl) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/joplin-v\d+\.\d+\.\d+\.apk)/, androidUrl); - // if (android32Url) content = content.replace(/(https:\/\/objects.joplinusercontent.com\/v\d+\.\d+\.\d+\/joplin-v\d+\.\d+\.\d+-32bit\.apk)/, android32Url); setReadmeContent(content); } diff --git a/packages/tools/website/updateDownloadPage.ts b/packages/tools/website/updateDownloadPage.ts index c06af73d1..7a6d48e10 100644 --- a/packages/tools/website/updateDownloadPage.ts +++ b/packages/tools/website/updateDownloadPage.ts @@ -1,7 +1,7 @@ import { readFile } from 'fs-extra'; import { rootDir, insertContentIntoFile } from '../tool-utils'; -async function getReadmeMd() { +async function getInstallMd() { return readFile(`${rootDir}/readme/install.md`, 'utf8'); } @@ -9,25 +9,28 @@ async function createDownloadButtonsHtml(readmeMd: string): Promise