mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 11:47:54 +01:00
desktop: ready app for mac store submission (#1057)
* desktop: add support for publishing to mac app store * ci: add step for deployment to testflight * ci: temporarily run build only on macos * config: cache `build:desktop` output in nx * ci: use `macos-12` instead of `macos-latest` * ci: no need to install `jq` * ci: build & deploy manually * ci: set env_vars using `env` key * ci: install packages before building * ci: build electron bundle before deployment * ci: install distribution signing cert * web: disable app store offending stuff for macos * ci: enable deployment to testflight * ci: remove cert installation to keychain * desktop: pass entitlement files through plutil * ci: use a single cert for everything * ci: fix altool command for uploading macOS package * ci: use env_vars for apiKey & apiIssuer * ci: install provisionprofile * ci: install provisioning profile in `./apps/web/desktop` dir * desktop: change bundleId to `org.streetwriters.notesnook` * ci: deploy & build in separate steps * ci: add jobs for linux & windows releasing * ci: checkout repo before anything else * ci: add `GH_TOKEN` to env & use ps syntax on windows * ci: get app store versions only for mac app * ci: correct order of steps Co-authored-by: ammarahm-ed <ammarahmed6506@gmail.com>
This commit is contained in:
242
.github/workflows/desktop.publish.yml
vendored
242
.github/workflows/desktop.publish.yml
vendored
@@ -3,11 +3,21 @@ name: Publish @notesnook/desktop
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release:
|
||||
publish-apple:
|
||||
type: boolean
|
||||
required: true
|
||||
default: false
|
||||
description: "Release after successful build?"
|
||||
default: true
|
||||
description: "Publish on Mac App Store?"
|
||||
publish-snap:
|
||||
type: boolean
|
||||
required: true
|
||||
default: true
|
||||
description: "Publish on Snapcraft?"
|
||||
publish-github:
|
||||
type: boolean
|
||||
required: true
|
||||
default: true
|
||||
description: "Publish on GitHub releases?"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -52,15 +62,173 @@ jobs:
|
||||
name: build
|
||||
path: apps/web/build/**/*
|
||||
|
||||
publish:
|
||||
name: Publish
|
||||
build-macos:
|
||||
name: Build macOS
|
||||
needs: build
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: macos-12
|
||||
|
||||
# Platforms to build on/for
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup notarization
|
||||
run: |
|
||||
mkdir -p ~/private_keys/
|
||||
echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8
|
||||
|
||||
- name: Collect app metadata
|
||||
id: app_metadata
|
||||
working-directory: ./apps/web/desktop
|
||||
run: |
|
||||
echo ::set-output name=apple_app_id::$(cat package.json | jq -r .appAppleId)
|
||||
echo ::set-output name=app_bundle_id::$(cat package.json | jq -r .build.appId)
|
||||
echo ::set-output name=app_version::$(cat package.json | jq -r .version)
|
||||
echo ::set-output name=bundle_version::$(cat package.json | jq -r .build.mac.bundleVersion)
|
||||
|
||||
- name: Get App Store Version
|
||||
id: appstore
|
||||
uses: streetwriters/appstore-connect-app-version@develop
|
||||
with:
|
||||
app-id: ${{ steps.app_metadata.outputs.apple_app_id }}
|
||||
key-id: ${{ secrets.api_key_id }}
|
||||
issuer-id: ${{ secrets.api_key_issuer_id }}
|
||||
private-key-raw: ${{ secrets.api_key }}
|
||||
platform: "MAC_OS"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/desktop/build
|
||||
|
||||
- name: Install packages
|
||||
run: npm i
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npm run build
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Install provisioning profile
|
||||
run: echo "${{ secrets.MAC_PROVISIONING_PROFILE }}" | base64 --decode > embedded.provisionprofile
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build app for Mac App Store
|
||||
if: inputs.publish-apple && steps.appstore.outputs.app-version-latest != steps.app_metadata.outputs.app_version
|
||||
env:
|
||||
CSC_LINK: ${{ secrets.mac_certs }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }}
|
||||
run: |
|
||||
npx electron-builder --mac mas --universal -p never
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build zip and dmg
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CSC_LINK: ${{ secrets.mac_certs }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }}
|
||||
run: |
|
||||
if [ ${{ inputs.publish-github }} == true ]; then
|
||||
npx electron-builder --mac zip dmg -p always
|
||||
else
|
||||
npx electron-builder --mac zip dmg -p never
|
||||
fi
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Deploy to Testflight
|
||||
if: inputs.publish-apple && steps.appstore.outputs.app-version-latest != steps.app_metadata.outputs.app_version
|
||||
env:
|
||||
API_KEY_ID: ${{ secrets.api_key_id }}
|
||||
API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }}
|
||||
run: |
|
||||
package=$(find ./dist/mas-universal/notesnook*.pkg)
|
||||
|
||||
echo "Uploading ${package} using altool..."
|
||||
|
||||
xcrun altool --upload-package $package -t osx --apiKey $API_KEY_ID --apiIssuer $API_KEY_ISSUER_ID --apple-id ${{ steps.app_metadata.outputs.apple_app_id }} --bundle-id ${{ steps.app_metadata.outputs.app_bundle_id }}--bundle-short-version-string ${{ steps.app_metadata.outputs.app_version }} --bundle-version ${{ steps.app_metadata.outputs.bundle_version }}
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
build-linux:
|
||||
name: Build for Linux
|
||||
needs: build
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Collect app metadata
|
||||
id: app_metadata
|
||||
working-directory: ./apps/web/desktop
|
||||
run: |
|
||||
echo ::set-output name=app_version::$(cat package.json | jq -r .version)
|
||||
|
||||
- name: Setup Snapcraft Auth
|
||||
if: inputs.publish-snap
|
||||
run: echo "SNAPCRAFT_STORE_CREDENTIALS=${{ secrets.snapcraft_token }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Snapcraft
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
if: inputs.publish-snap
|
||||
|
||||
- name: Get version info from Snapcraft
|
||||
if: inputs.publish-snap
|
||||
id: snapcraft
|
||||
run:
|
||||
echo ::set-output name=is_published::$(snapcraft status notesnook | grep ${{ steps.app_metadata.outputs.app_version }} | wc -l)
|
||||
echo $is_published
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build
|
||||
path: ./apps/web/desktop/build
|
||||
|
||||
- name: Install packages
|
||||
run: npm i
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npm run build
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build snap
|
||||
if: inputs.publish-snap && steps.snapcraft.outputs.is_published <= 0
|
||||
run: |
|
||||
npx electron-builder --linux snap -p never
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build AppImage deb and rpm
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
if [ ${{ inputs.publish-github }} == true ]; then
|
||||
npx electron-builder --linux AppImage deb rpm -p always
|
||||
else
|
||||
npx electron-builder --linux AppImage deb rpm -p never
|
||||
fi
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Publish on Snapcraft
|
||||
if: inputs.publish-snap && steps.snapcraft.outputs.is_published <= 0
|
||||
run: |
|
||||
snapcraft upload --release=stable ./dist/notesnook_linux_amd64.snap
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
build-windows:
|
||||
name: Build for Windows
|
||||
needs: build
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
@@ -77,41 +245,21 @@ jobs:
|
||||
name: build
|
||||
path: ./apps/web/desktop/build
|
||||
|
||||
- name: Setup Snapcraft Auth
|
||||
run: echo "SNAPCRAFT_STORE_CREDENTIALS=${{ secrets.snapcraft_token }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Snapcraft
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
|
||||
- name: Prepare for app notarization (macOS)
|
||||
if: startsWith(matrix.os, 'macos')
|
||||
# Import Apple API key for app notarization on macOS
|
||||
run: |
|
||||
mkdir -p ~/private_keys/
|
||||
echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8
|
||||
|
||||
- name: Build/release Electron app
|
||||
uses: samuelmeuli/action-electron-builder@master
|
||||
with:
|
||||
package_root: ./apps/web/desktop
|
||||
# GitHub token, automatically provided to the action
|
||||
# (No need to define this secret in the repo settings)
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
build_script_name: "build"
|
||||
# macOS code signing certificate
|
||||
mac_certs: ${{ secrets.mac_certs }}
|
||||
mac_certs_password: ${{ secrets.mac_certs_password }}
|
||||
|
||||
# If the commit is tagged with a version (e.g. "v1.0.0"),
|
||||
# release the app after building
|
||||
release: ${{ inputs.release }}
|
||||
env:
|
||||
# macOS notarization API key
|
||||
API_KEY_ID: ${{ secrets.api_key_id }}
|
||||
API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }}
|
||||
|
||||
- name: Publish on Snapcraft
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: snapcraft upload --release=stable ./dist/notesnook_linux_amd64.snap
|
||||
- name: Install packages
|
||||
run: npm i
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build Electron wrapper
|
||||
run: npm run build
|
||||
working-directory: ./apps/web/desktop
|
||||
|
||||
- name: Build app
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
if (${{ inputs.publish-github }} == true) {
|
||||
npx electron-builder --win -p always
|
||||
} else {
|
||||
npx electron-builder --win -p never
|
||||
}
|
||||
working-directory: ./apps/web/desktop
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
14
apps/web/desktop/assets/entitlements.mas.inherit.plist
Normal file
14
apps/web/desktop/assets/entitlements.mas.inherit.plist
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.inherit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
30
apps/web/desktop/assets/entitlements.mas.plist
Normal file
30
apps/web/desktop/assets/entitlements.mas.plist
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.application-identifier</key>
|
||||
<string>53CWBG3QUC.org.streetwriters.notesnook</string>
|
||||
<key>com.apple.developer.team-identifier</key>
|
||||
<string>53CWBG3QUC</string>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>53CWBG3QUC.org.streetwriters.notesnook</string>
|
||||
</array>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.print</key>
|
||||
<true/>
|
||||
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
|
||||
<array>
|
||||
<string>/Documents/Notesnook/</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -3,6 +3,7 @@
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "2.2.0",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./build/electron.js",
|
||||
"homepage": "https://notesnook.com/",
|
||||
@@ -35,7 +36,7 @@
|
||||
"url": "https://streetwriters.co"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.streetwriters.notesnook",
|
||||
"appId": "org.streetwriters.notesnook",
|
||||
"productName": "Notesnook",
|
||||
"copyright": "Copyright © 2022 Streetwriters (Private) Ltd.",
|
||||
"artifactName": "notesnook_${os}_${arch}.${ext}",
|
||||
@@ -68,6 +69,8 @@
|
||||
"afterSign": "electron-builder-notarize",
|
||||
"afterPack": "./scripts/removeLocales.js",
|
||||
"mac": {
|
||||
"bundleVersion": "220",
|
||||
"minimumSystemVersion": "10.14.0",
|
||||
"target": [
|
||||
{
|
||||
"target": "dmg",
|
||||
@@ -109,6 +112,12 @@
|
||||
"icon": "assets/icons/app.icns",
|
||||
"title": "Install Notesnook"
|
||||
},
|
||||
"mas": {
|
||||
"entitlements": "assets/entitlements.mas.plist",
|
||||
"entitlementsInherit": "assets/entitlements.mas.inherit.plist",
|
||||
"entitlementsLoginHelper": "assets/entitlements.mas.loginhelper.plist",
|
||||
"hardenedRuntime": true
|
||||
},
|
||||
"win": {
|
||||
"target": [
|
||||
"nsis",
|
||||
|
||||
@@ -21,6 +21,7 @@ const { contextBridge, ipcRenderer } = require("electron");
|
||||
|
||||
// Expose protected methods that allow the renderer process to use
|
||||
// the ipcRenderer without exposing the entire object
|
||||
contextBridge.exposeInMainWorld("os", process.platform);
|
||||
contextBridge.exposeInMainWorld("api", {
|
||||
send: (channel, data) => {
|
||||
// whitelist channels
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
{
|
||||
"applinks":{
|
||||
"apps":[
|
||||
|
||||
],
|
||||
"details":[
|
||||
{
|
||||
"appID":"53CWBG3QUC.com.streetwriters.notesnook",
|
||||
"paths":[
|
||||
"*",
|
||||
"/account/verified"
|
||||
],
|
||||
"components":[
|
||||
{
|
||||
"/":"/account/verified"
|
||||
},
|
||||
{
|
||||
"/":"*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"applinks": {
|
||||
"apps": [],
|
||||
"details": [
|
||||
{
|
||||
"appID": "53CWBG3QUC.org.streetwriters.notesnook",
|
||||
"paths": [
|
||||
"*",
|
||||
"/account/verified"
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"/": "/account/verified"
|
||||
},
|
||||
{
|
||||
"/": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import { db } from "../../../common/db";
|
||||
import { useCheckoutStore } from "./store";
|
||||
import { getCurrencySymbol } from "./helpers";
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import { isMacApp } from "../../../utils/platform";
|
||||
|
||||
type BuyDialogProps = {
|
||||
couponCode?: string;
|
||||
@@ -283,7 +284,13 @@ function TrialOrUpgrade(props: TrialOrUpgradeProps) {
|
||||
{formatPeriod(plan.period)}
|
||||
</Text>
|
||||
)}
|
||||
{user ? (
|
||||
{isMacApp() ? (
|
||||
<>
|
||||
<Text variant={"subBody"} mt={2} sx={{ textAlign: "center" }}>
|
||||
You cannot upgrade from the macOS app.
|
||||
</Text>
|
||||
</>
|
||||
) : user ? (
|
||||
<>
|
||||
<Button
|
||||
variant="primary"
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Text, Flex, Box } from "@theme-ui/components";
|
||||
import { isMacApp } from "../../../utils/platform";
|
||||
import {
|
||||
Accent,
|
||||
Android,
|
||||
@@ -74,6 +75,7 @@ type Section = {
|
||||
info?: string;
|
||||
pro?: boolean;
|
||||
features?: Feature[];
|
||||
isVisible?: () => boolean;
|
||||
};
|
||||
|
||||
const sections: Section[] = [
|
||||
@@ -120,6 +122,7 @@ const sections: Section[] = [
|
||||
title: "100% cross platform",
|
||||
detail: "Notesnook is available on all major platforms — for everyone.",
|
||||
columns: 8,
|
||||
isVisible: () => !isMacApp(),
|
||||
features: [
|
||||
{
|
||||
id: "ios",
|
||||
@@ -367,86 +370,90 @@ export function Features() {
|
||||
pt={6}
|
||||
bg="background"
|
||||
>
|
||||
{sections.map((section) => (
|
||||
<Flex
|
||||
key={section.title}
|
||||
px={6}
|
||||
pb={50}
|
||||
sx={{ flexDirection: "column" }}
|
||||
>
|
||||
{section.pro && (
|
||||
<Flex
|
||||
bg="bgSecondary"
|
||||
px={2}
|
||||
py="2px"
|
||||
sx={{ borderRadius: 50, alignSelf: "start" }}
|
||||
mb={1}
|
||||
>
|
||||
<Pro color="primary" size={16} />
|
||||
<Text variant="body" ml={"2px"} sx={{ color: "primary" }}>
|
||||
Pro
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
<Text variant="body" sx={{ fontSize: "1.3rem" }}>
|
||||
{section.title}
|
||||
</Text>
|
||||
<Text
|
||||
variant="body"
|
||||
mt={1}
|
||||
sx={{ fontSize: "title", color: "fontTertiary" }}
|
||||
{sections.map((section) => {
|
||||
if (section.isVisible && !section.isVisible()) return null;
|
||||
|
||||
return (
|
||||
<Flex
|
||||
key={section.title}
|
||||
px={6}
|
||||
pb={50}
|
||||
sx={{ flexDirection: "column" }}
|
||||
>
|
||||
{section.detail}
|
||||
</Text>
|
||||
{section.features && (
|
||||
<Box
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: section.columns
|
||||
? "1fr ".repeat(section.columns)
|
||||
: "1fr 1fr 1fr",
|
||||
gap: 3
|
||||
}}
|
||||
mt={4}
|
||||
>
|
||||
{section.features.map((feature) => (
|
||||
<Flex
|
||||
key={feature.id}
|
||||
sx={{ flexDirection: "column", alignItems: "start" }}
|
||||
>
|
||||
{feature.icon && (
|
||||
<feature.icon size={20} color="text" sx={{ mb: 1 }} />
|
||||
)}
|
||||
{feature.pro && (
|
||||
<Flex
|
||||
sx={{ alignItems: "center", justifyContent: "center" }}
|
||||
>
|
||||
<Pro color="primary" size={14} />
|
||||
<Text
|
||||
variant="subBody"
|
||||
ml={"2px"}
|
||||
sx={{ color: "primary" }}
|
||||
>
|
||||
Pro
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
{feature.title && (
|
||||
<Text variant="body" sx={{ fontSize: "subtitle" }}>
|
||||
{feature.title}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{section.info && (
|
||||
<Text mt={1} variant="subBody">
|
||||
{section.info}
|
||||
{section.pro && (
|
||||
<Flex
|
||||
bg="bgSecondary"
|
||||
px={2}
|
||||
py="2px"
|
||||
sx={{ borderRadius: 50, alignSelf: "start" }}
|
||||
mb={1}
|
||||
>
|
||||
<Pro color="primary" size={16} />
|
||||
<Text variant="body" ml={"2px"} sx={{ color: "primary" }}>
|
||||
Pro
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
<Text variant="body" sx={{ fontSize: "1.3rem" }}>
|
||||
{section.title}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
))}
|
||||
<Text
|
||||
variant="body"
|
||||
mt={1}
|
||||
sx={{ fontSize: "title", color: "fontTertiary" }}
|
||||
>
|
||||
{section.detail}
|
||||
</Text>
|
||||
{section.features && (
|
||||
<Box
|
||||
sx={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: section.columns
|
||||
? "1fr ".repeat(section.columns)
|
||||
: "1fr 1fr 1fr",
|
||||
gap: 3
|
||||
}}
|
||||
mt={4}
|
||||
>
|
||||
{section.features.map((feature) => (
|
||||
<Flex
|
||||
key={feature.id}
|
||||
sx={{ flexDirection: "column", alignItems: "start" }}
|
||||
>
|
||||
{feature.icon && (
|
||||
<feature.icon size={20} color="text" sx={{ mb: 1 }} />
|
||||
)}
|
||||
{feature.pro && (
|
||||
<Flex
|
||||
sx={{ alignItems: "center", justifyContent: "center" }}
|
||||
>
|
||||
<Pro color="primary" size={14} />
|
||||
<Text
|
||||
variant="subBody"
|
||||
ml={"2px"}
|
||||
sx={{ color: "primary" }}
|
||||
>
|
||||
Pro
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
{feature.title && (
|
||||
<Text variant="body" sx={{ fontSize: "subtitle" }}>
|
||||
{feature.title}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{section.info && (
|
||||
<Text mt={1} variant="subBody">
|
||||
{section.info}
|
||||
</Text>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export function getPlatform() {
|
||||
if (window.os) return window.os;
|
||||
|
||||
var userAgent = window.navigator.userAgent,
|
||||
platform = window.navigator.platform,
|
||||
macosPlatforms = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"],
|
||||
@@ -124,6 +126,10 @@ export function isDesktop() {
|
||||
return "api" in window;
|
||||
}
|
||||
|
||||
export function isMacApp() {
|
||||
return true; // window.os === "darwin";
|
||||
}
|
||||
|
||||
export function isTesting() {
|
||||
return !!process.env.REACT_APP_TEST;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ import { appVersion } from "../utils/version";
|
||||
import { CHECK_IDS } from "@notesnook/core/common";
|
||||
import Tip from "../components/tip";
|
||||
import Toggle from "../components/toggle";
|
||||
import { isDesktop } from "../utils/platform";
|
||||
import { isDesktop, isMacApp } from "../utils/platform";
|
||||
import Vault from "../common/vault";
|
||||
import { isUserPremium } from "../hooks/use-is-user-premium";
|
||||
import { Slider } from "@theme-ui/components";
|
||||
@@ -103,9 +103,13 @@ const otherItems = [
|
||||
link: "https://discord.com/invite/zQBK97EE22"
|
||||
},
|
||||
{
|
||||
title: "Download for iOS & Android",
|
||||
description: "Notesnook is available on Android & iOS",
|
||||
link: "https://notesnook.com/"
|
||||
title: isMacApp() ? "Download for iOS" : "Download for iOS & Android",
|
||||
description: isMacApp()
|
||||
? "Notesnook is also available on iOS"
|
||||
: "Notesnook is available on Android & iOS",
|
||||
link: isMacApp()
|
||||
? "https://apps.apple.com/us/app/notesnook-take-private-notes/id1544027013"
|
||||
: "https://notesnook.com/"
|
||||
},
|
||||
{
|
||||
title: "Documentation",
|
||||
|
||||
Reference in New Issue
Block a user