mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
web: fix service worker to allow Notesnook to behave as a PWA again (#2905)
* web: make service worker work again * web: only enable sourcemap during dev
This commit is contained in:
@@ -1,47 +0,0 @@
|
||||
const { execSync } = require("child_process");
|
||||
const { cpus, networkInterfaces } = require("os");
|
||||
const { version } = require("./package.json");
|
||||
const ip = require("ip");
|
||||
|
||||
const NUM_CPUS = cpus().length;
|
||||
const IS_CI = process.env.CI;
|
||||
const gitHash = execSync("git rev-parse --short HEAD").toString().trim();
|
||||
const APP_VERSION = version.replaceAll(".", "");
|
||||
console.log("App version:", APP_VERSION);
|
||||
console.log("Ip address:", ip.address());
|
||||
module.exports = {
|
||||
beta: {
|
||||
REACT_APP_BETA: true
|
||||
},
|
||||
test: {
|
||||
TEST_ALL: true
|
||||
},
|
||||
all: {
|
||||
UV_THREADPOOL_SIZE: IS_CI ? NUM_CPUS : 2,
|
||||
GENERATE_SOURCEMAP: process.env.NODE_ENV === "development",
|
||||
// INLINE_RUNTIME_CHUNK: false,
|
||||
// DISABLE_ESLINT_PLUGIN: true,
|
||||
REACT_APP_GIT_HASH: gitHash,
|
||||
REACT_APP_VERSION: APP_VERSION
|
||||
},
|
||||
dev: {
|
||||
REACT_APP_LOCALHOST: ip.address()
|
||||
},
|
||||
web: {
|
||||
REACT_APP_PLATFORM: "web"
|
||||
},
|
||||
debug: {
|
||||
PWDEBUG: 1,
|
||||
DEBUG: "pw:api"
|
||||
},
|
||||
silent: {
|
||||
REACT_APP_TEST: true
|
||||
// DISABLE_ESLINT_PLUGIN: "true"
|
||||
// FAST_REFRESH: "false",
|
||||
// BROWSER: "none"
|
||||
},
|
||||
desktop: {
|
||||
// BROWSER: "none",
|
||||
REACT_APP_PLATFORM: "desktop"
|
||||
}
|
||||
};
|
||||
1083
apps/web/package-lock.json
generated
1083
apps/web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -82,8 +82,8 @@
|
||||
"autoprefixer": "^10.4.14",
|
||||
"buffer": "^6.0.3",
|
||||
"chalk": "^4.1.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv": "^10.0.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"find-process": "^1.4.4",
|
||||
"happy-dom": "^8.9.0",
|
||||
@@ -111,13 +111,13 @@
|
||||
"@types/react-dom@>17": "17.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "env-cmd -e all,dev,web vite",
|
||||
"start:desktop": "env-cmd -e all,desktop vite",
|
||||
"start": "cross-env PLATFORM=web vite",
|
||||
"start:desktop": "cross-env PLATFORM=desktop vite",
|
||||
"start:test": "serve -s build/ -p 3000",
|
||||
"build": "env-cmd -e all,web vite build",
|
||||
"build:test": "env-cmd -e all,dev,web,silent vite build",
|
||||
"build:beta": "env-cmd -e all,web,beta vite build",
|
||||
"build:desktop": "env-cmd -e all,desktop vite build",
|
||||
"build": "cross-env PLATFORM=web vite build",
|
||||
"build:test": "cross-env PLATFORM=web TEST=true vite build",
|
||||
"build:beta": "cross-env PLATFORM=web BETA=true vite build",
|
||||
"build:desktop": "cross-env PLATFORM=desktop vite build",
|
||||
"test": "playwright test -u"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
@@ -39,7 +39,7 @@ import {
|
||||
showOnboardingDialog
|
||||
} from "./common/dialog-controller";
|
||||
import useSystemTheme from "./hooks/use-system-theme";
|
||||
import { isTesting } from "./utils/platform";
|
||||
|
||||
import { updateStatus, removeStatus, getStatus } from "./hooks/use-status";
|
||||
import { showToast } from "./utils/toast";
|
||||
import { interruptedOnboarding } from "./dialogs/onboarding-dialog";
|
||||
@@ -199,7 +199,7 @@ export default function AppEffects({ setShow }: AppEffectsProps) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!dialogAnnouncements.length || isTesting()) return;
|
||||
if (!dialogAnnouncements.length || IS_TESTING) return;
|
||||
(async () => {
|
||||
await showAnnouncementDialog(dialogAnnouncements[0]);
|
||||
})();
|
||||
|
||||
@@ -111,11 +111,7 @@ function SuspenseLoader<TComponent extends React.JSXElementConstructor<any>>({
|
||||
props: any
|
||||
) => React.ReactComponentElement<any, any>;
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
import.meta.env.REACT_APP_PLATFORM === "desktop" ? null : fallback
|
||||
}
|
||||
>
|
||||
<Suspense fallback={IS_DESKTOP_APP ? null : fallback}>
|
||||
<Component {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
@@ -47,7 +47,7 @@ async function initializeDatabase(persistence: DatabasePersistence) {
|
||||
FS,
|
||||
new Compressor()
|
||||
);
|
||||
// if (isTesting()) {
|
||||
// if (IS_TESTING) {
|
||||
|
||||
// } else {
|
||||
// db.host({
|
||||
|
||||
@@ -27,7 +27,7 @@ import Config from "../utils/config";
|
||||
import { hashNavigate, getCurrentHash } from "../navigation";
|
||||
import { db } from "./db";
|
||||
import { sanitizeFilename } from "@notesnook/common";
|
||||
import { isDesktop, isTesting } from "../utils/platform";
|
||||
|
||||
import { store as userstore } from "../stores/user-store";
|
||||
import FileSaver from "file-saver";
|
||||
import { showToast } from "../utils/toast";
|
||||
@@ -66,7 +66,7 @@ export const CREATE_BUTTON_MAP = {
|
||||
|
||||
export async function introduceFeatures() {
|
||||
const hash = getCurrentHash().replace("#", "");
|
||||
if (!!hash || isTesting()) return;
|
||||
if (!!hash || IS_TESTING) return;
|
||||
const features = [];
|
||||
for (let feature of features) {
|
||||
if (!Config.get(`feature:${feature}`)) {
|
||||
@@ -95,7 +95,7 @@ export async function createBackup() {
|
||||
const filename = sanitizeFilename(`notesnook-backup-${getFormattedDate()}`);
|
||||
|
||||
const ext = "nnbackup";
|
||||
if (isDesktop()) {
|
||||
if (IS_DESKTOP_APP) {
|
||||
const directory = Config.get(
|
||||
"backupStorageLocation",
|
||||
PATHS.backupsDirectory
|
||||
@@ -189,7 +189,7 @@ export function totalSubscriptionConsumed(user) {
|
||||
}
|
||||
|
||||
export async function showUpgradeReminderDialogs() {
|
||||
if (isTesting()) return;
|
||||
if (IS_TESTING) return;
|
||||
|
||||
const user = userstore.get().user;
|
||||
if (!user || !user.subscription || user.subscription?.expiry === 0) return;
|
||||
|
||||
@@ -25,7 +25,7 @@ import { Backup, User, Email, Warn, Icon } from "../components/icons";
|
||||
import dayjs from "dayjs";
|
||||
import { showBuyDialog, showRecoveryKeyDialog } from "./dialog-controller";
|
||||
import { hardNavigate, hashNavigate } from "../navigation";
|
||||
import { isDesktop, isTesting } from "../utils/platform";
|
||||
|
||||
import { isUserPremium } from "../hooks/use-is-user-premium";
|
||||
import { showToast } from "../utils/toast";
|
||||
import { TaskScheduler } from "../utils/task-scheduler";
|
||||
@@ -176,9 +176,9 @@ function isIgnored(key: keyof typeof NoticesData) {
|
||||
|
||||
var openedToast: { hide: () => void } | null = null;
|
||||
async function saveBackup() {
|
||||
if (isDesktop()) {
|
||||
if (IS_DESKTOP_APP) {
|
||||
await createBackup();
|
||||
} else if (isUserPremium() && !isTesting()) {
|
||||
} else if (isUserPremium() && !IS_TESTING) {
|
||||
if (openedToast !== null) return;
|
||||
openedToast = showToast(
|
||||
"success",
|
||||
|
||||
@@ -85,7 +85,7 @@ type TipTapProps = {
|
||||
fontFamily: string;
|
||||
};
|
||||
|
||||
const SAVE_INTERVAL = import.meta.env.REACT_APP_TEST ? 100 : 300;
|
||||
const SAVE_INTERVAL = IS_TESTING ? 100 : 300;
|
||||
|
||||
function save(
|
||||
sessionId: number,
|
||||
|
||||
@@ -48,7 +48,6 @@ import { useStore as useUserStore } from "../../stores/user-store";
|
||||
import { useStore as useThemeStore } from "../../stores/theme-store";
|
||||
import useLocation from "../../hooks/use-location";
|
||||
import { FlexScrollContainer } from "../scroll-container";
|
||||
import { isDesktop } from "../../utils/platform";
|
||||
|
||||
type Route = {
|
||||
title: string;
|
||||
@@ -192,7 +191,7 @@ function NavigationMenu(props: NavigationMenuProps) {
|
||||
))}
|
||||
{colors.map((color, index) => (
|
||||
<NavigationItem
|
||||
animate={!isDesktop()}
|
||||
animate={!IS_DESKTOP_APP}
|
||||
index={index}
|
||||
isTablet={isTablet}
|
||||
key={color.id}
|
||||
@@ -221,7 +220,7 @@ function NavigationMenu(props: NavigationMenuProps) {
|
||||
/>
|
||||
{shortcuts.map((item, index) => (
|
||||
<NavigationItem
|
||||
animate={!isDesktop()}
|
||||
animate={!IS_DESKTOP_APP}
|
||||
index={colors.length - 1 + index}
|
||||
isTablet={isTablet}
|
||||
key={item.id}
|
||||
|
||||
@@ -31,20 +31,17 @@ import {
|
||||
PricingInfo
|
||||
} from "./types";
|
||||
|
||||
// const isDev = false; // import.meta.env.NODE_ENV === "development";
|
||||
// const isDev = false; // import.meta.env.DEV;
|
||||
// const VENDOR_ID = isDev ? 1506 : 128190;
|
||||
const PADDLE_ORIGIN =
|
||||
import.meta.env.NODE_ENV === "development"
|
||||
? "https://sandbox-buy.paddle.com"
|
||||
: "https://buy.paddle.com";
|
||||
const CHECKOUT_CREATE_ORIGIN =
|
||||
import.meta.env.NODE_ENV === "development"
|
||||
? "https://sandbox-create-checkout.paddle.com"
|
||||
: "https://create-checkout.paddle.com";
|
||||
const CHECKOUT_SERVICE_ORIGIN =
|
||||
import.meta.env.NODE_ENV === "development"
|
||||
? "https://sandbox-checkout-service.paddle.com"
|
||||
: "https://checkout-service.paddle.com";
|
||||
const PADDLE_ORIGIN = import.meta.env.DEV
|
||||
? "https://sandbox-buy.paddle.com"
|
||||
: "https://buy.paddle.com";
|
||||
const CHECKOUT_CREATE_ORIGIN = import.meta.env.DEV
|
||||
? "https://sandbox-create-checkout.paddle.com"
|
||||
: "https://create-checkout.paddle.com";
|
||||
const CHECKOUT_SERVICE_ORIGIN = import.meta.env.DEV
|
||||
? "https://sandbox-checkout-service.paddle.com"
|
||||
: "https://checkout-service.paddle.com";
|
||||
|
||||
const SUBSCRIBED_EVENTS: PaddleEvents[] = [
|
||||
PaddleEvents["Checkout.Loaded"],
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { isTesting } from "../../utils/platform";
|
||||
|
||||
import { Period, Plan } from "./types";
|
||||
|
||||
type PlanMetadata = {
|
||||
@@ -32,7 +32,7 @@ export const DEFAULT_PLANS: Plan[] = [
|
||||
country: "PK",
|
||||
currency: "USD",
|
||||
discount: 0,
|
||||
id: import.meta.env.NODE_ENV === "development" ? "9822" : "648884",
|
||||
id: import.meta.env.DEV ? "9822" : "648884",
|
||||
price: { gross: 4.49, net: 0, tax: 0 }
|
||||
},
|
||||
{
|
||||
@@ -40,7 +40,7 @@ export const DEFAULT_PLANS: Plan[] = [
|
||||
country: "PK",
|
||||
currency: "USD",
|
||||
discount: 0,
|
||||
id: import.meta.env.NODE_ENV === "development" ? "50305" : "658759",
|
||||
id: import.meta.env.DEV ? "50305" : "658759",
|
||||
price: { gross: 49.99, net: 0, tax: 0 }
|
||||
}
|
||||
];
|
||||
@@ -52,8 +52,7 @@ export const PLAN_METADATA: Record<Period, PlanMetadata> = {
|
||||
|
||||
let CACHED_PLANS: Plan[];
|
||||
export async function getPlans(): Promise<Plan[] | null> {
|
||||
if (isTesting() || import.meta.env.NODE_ENV === "development")
|
||||
return DEFAULT_PLANS;
|
||||
if (IS_TESTING || import.meta.env.DEV) return DEFAULT_PLANS;
|
||||
if (CACHED_PLANS) return CACHED_PLANS;
|
||||
|
||||
const url = `https://notesnook.com/api/v1/prices/products/web`;
|
||||
|
||||
@@ -22,7 +22,7 @@ import Dialog from "../components/dialog";
|
||||
import { getHomeRoute, hardNavigate } from "../navigation";
|
||||
import { appVersion } from "../utils/version";
|
||||
import Config from "../utils/config";
|
||||
import { isTesting } from "../utils/platform";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { ArrowRight, Checkmark, Icon, Warn } from "../components/icons";
|
||||
|
||||
@@ -106,7 +106,7 @@ const features: Record<FeatureKeys, Feature> = {
|
||||
appVersion.isBeta || Config.has((k) => k.endsWith(":highlights"));
|
||||
if (!hasShownAny) Config.set(key, true);
|
||||
|
||||
return hasShownAny && !isTesting() && !hasShownBefore;
|
||||
return hasShownAny && !IS_TESTING && !hasShownBefore;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ import { createBackup } from "../common";
|
||||
import { db } from "../common/db";
|
||||
import { Perform } from "../common/dialog-controller";
|
||||
import { TaskManager } from "../common/task-manager";
|
||||
import { isDesktop } from "../utils/platform";
|
||||
|
||||
import Dialog from "../components/dialog";
|
||||
|
||||
type MigrationProgressEvent = {
|
||||
@@ -74,7 +74,7 @@ export default function MigrationDialog(props: MigrationDialogProps) {
|
||||
}, [props]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDesktop()) {
|
||||
if (IS_DESKTOP_APP) {
|
||||
(async () => {
|
||||
await startMigration();
|
||||
})();
|
||||
@@ -115,7 +115,7 @@ export default function MigrationDialog(props: MigrationDialogProps) {
|
||||
);
|
||||
}
|
||||
|
||||
if (isDesktop() || isProcessing) return null;
|
||||
if (IS_DESKTOP_APP || isProcessing) return null;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
|
||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { SettingsGroup } from "./types";
|
||||
import { useStore as useSettingStore } from "../../stores/setting-store";
|
||||
import { useStore as useThemeStore } from "../../stores/theme-store";
|
||||
import { isDesktop } from "../../utils/platform";
|
||||
|
||||
import { AccentColors } from "./components/accent-colors";
|
||||
|
||||
export const AppearanceSettings: SettingsGroup[] = [
|
||||
@@ -72,7 +72,7 @@ export const AppearanceSettings: SettingsGroup[] = [
|
||||
key: "zoom-factor",
|
||||
title: "Zoom factor",
|
||||
description: "Zoom in or out the app content.",
|
||||
isHidden: () => !isDesktop(),
|
||||
isHidden: () => !IS_DESKTOP_APP,
|
||||
onStateChange: (listener) =>
|
||||
useThemeStore.subscribe(
|
||||
(s) => [s.theme, s.followSystemTheme],
|
||||
|
||||
@@ -25,7 +25,7 @@ import { isUserPremium } from "../../hooks/use-is-user-premium";
|
||||
import { createBackup, importBackup, verifyAccount } from "../../common";
|
||||
import { db } from "../../common/db";
|
||||
import { exportNotes } from "../../common/export";
|
||||
import { isDesktop, isTesting } from "../../utils/platform";
|
||||
|
||||
import { desktop } from "../../common/desktop-bridge";
|
||||
import { PATHS } from "@notesnook/desktop";
|
||||
|
||||
@@ -56,7 +56,7 @@ export const BackupExportSettings: SettingsGroup[] = [
|
||||
key: "restore-backup",
|
||||
title: "Restore backup",
|
||||
description: "Restore a backup file from your disk drive.",
|
||||
isHidden: () => !useUserStore.getState().isLoggedIn && !isTesting(),
|
||||
isHidden: () => !useUserStore.getState().isLoggedIn && !IS_TESTING,
|
||||
components: [
|
||||
{
|
||||
type: "button",
|
||||
@@ -71,8 +71,8 @@ export const BackupExportSettings: SettingsGroup[] = [
|
||||
},
|
||||
{
|
||||
key: "auto-backup",
|
||||
title: isDesktop() ? "Automatic backups" : "Backup reminders",
|
||||
description: isDesktop()
|
||||
title: IS_DESKTOP_APP ? "Automatic backups" : "Backup reminders",
|
||||
description: IS_DESKTOP_APP
|
||||
? "Backup all your data automatically at a set interval."
|
||||
: "You will be shown regular reminders to backup your data.",
|
||||
isHidden: () => !isUserPremium(),
|
||||
@@ -119,7 +119,7 @@ export const BackupExportSettings: SettingsGroup[] = [
|
||||
key: "backup-directory",
|
||||
title: "Backups directory",
|
||||
description: "Select directory to store all backup files.",
|
||||
isHidden: () => !isDesktop(),
|
||||
isHidden: () => !IS_DESKTOP_APP,
|
||||
components: [
|
||||
{
|
||||
type: "button",
|
||||
|
||||
@@ -27,7 +27,7 @@ import { useStore as useSettingStore } from "../../stores/setting-store";
|
||||
import { getFonts } from "@notesnook/editor";
|
||||
import { useSpellChecker } from "../../hooks/use-spell-checker";
|
||||
import { SpellCheckerLanguages } from "./components/spell-checker-languages";
|
||||
import { isDesktop } from "../../utils/platform";
|
||||
|
||||
import { CustomizeToolbar } from "./components/customize-toolbar";
|
||||
|
||||
export const EditorSettings: SettingsGroup[] = [
|
||||
@@ -118,7 +118,7 @@ symbols (e.g. 202305261253)`,
|
||||
key: "spell-check",
|
||||
section: "editor",
|
||||
header: "Spell check",
|
||||
isHidden: () => !isDesktop(),
|
||||
isHidden: () => !IS_DESKTOP_APP,
|
||||
onRender: () => {
|
||||
useSpellChecker.getState().refresh();
|
||||
},
|
||||
|
||||
@@ -51,7 +51,7 @@ import { SyncSettings } from "./sync-settings";
|
||||
import { BehaviourSettings } from "./behaviour-settings";
|
||||
import { DesktopIntegrationSettings } from "./desktop-integration-settings";
|
||||
import { NotificationsSettings } from "./notifications-settings";
|
||||
import { isDesktop } from "../../utils/platform";
|
||||
|
||||
import { BackupExportSettings } from "./backup-export-settings";
|
||||
import { ImporterSettings } from "./importer-settings";
|
||||
import { VaultSettings } from "./vault-settings";
|
||||
@@ -105,7 +105,7 @@ const sectionGroups: SectionGroup[] = [
|
||||
key: "desktop",
|
||||
title: "Desktop integration",
|
||||
icon: Desktop,
|
||||
isHidden: () => !isDesktop()
|
||||
isHidden: () => !IS_DESKTOP_APP
|
||||
},
|
||||
{ key: "notifications", title: "Notifications", icon: Notification }
|
||||
]
|
||||
|
||||
@@ -81,7 +81,7 @@ What data is collected & when?`,
|
||||
"Prevent Notesnook app from being captured by any screen capturing software like TeamViewer & AnyDesk.",
|
||||
onStateChange: (listener) =>
|
||||
useSettingStore.subscribe((s) => s.privacyMode, listener),
|
||||
isHidden: () => !isDesktop() || getPlatform() === "linux",
|
||||
isHidden: () => !IS_DESKTOP_APP || getPlatform() === "linux",
|
||||
components: [
|
||||
{
|
||||
type: "toggle",
|
||||
|
||||
9
apps/web/src/global.d.ts
vendored
9
apps/web/src/global.d.ts
vendored
@@ -16,11 +16,20 @@ GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* eslint-disable no-var */
|
||||
|
||||
import "vite/client";
|
||||
import "vite-plugin-svgr/client";
|
||||
|
||||
declare global {
|
||||
var PUBLIC_URL: string;
|
||||
var APP_VERSION: string;
|
||||
var GIT_HASH: string;
|
||||
var IS_DESKTOP_APP: boolean;
|
||||
var IS_TESTING: boolean;
|
||||
var PLATFORM: "web" | "desktop";
|
||||
var IS_BETA: boolean;
|
||||
|
||||
interface Window {
|
||||
os?: () => NodeJS.Platform | "mas";
|
||||
NativeNNCrypto?: new () => import("@notesnook/crypto").NNCrypto;
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { isDesktop } from "../utils/platform";
|
||||
|
||||
import { checkForUpdate } from "../utils/updater";
|
||||
import { AppEventManager, AppEvents } from "../common/app-events";
|
||||
|
||||
@@ -57,7 +57,7 @@ export function useAutoUpdater() {
|
||||
}
|
||||
|
||||
function updateNotAvailable() {
|
||||
if (isDesktop()) changeStatus({ type: "updated" });
|
||||
if (IS_DESKTOP_APP) changeStatus({ type: "updated" });
|
||||
else changeStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import "allotment/dist/style.css";
|
||||
import "../utils/analytics";
|
||||
import "../app.css";
|
||||
|
||||
if (import.meta.env.NODE_ENV === "production") {
|
||||
console.log = () => {};
|
||||
}
|
||||
// if (import.meta.env.PROD) {
|
||||
// console.log = () => {};
|
||||
// }
|
||||
|
||||
const memory = {
|
||||
isDatabaseLoaded: false
|
||||
@@ -45,4 +45,4 @@ export async function loadDatabase(persistence: "db" | "memory" = "db") {
|
||||
|
||||
await initializeDatabase(persistence);
|
||||
memory.isDatabaseLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
useStore as useUserStore,
|
||||
store as userstore
|
||||
} from "../stores/user-store";
|
||||
import { isTesting } from "../utils/platform";
|
||||
|
||||
export function useIsUserPremium() {
|
||||
const user = useUserStore((store) => store.user);
|
||||
@@ -30,7 +29,7 @@ export function useIsUserPremium() {
|
||||
}
|
||||
|
||||
export function isUserPremium(user?: User) {
|
||||
if (isTesting()) return true;
|
||||
if (IS_TESTING) return true;
|
||||
if (!user) user = userstore.get().user;
|
||||
|
||||
const subStatus = user?.subscription?.type;
|
||||
|
||||
@@ -23,7 +23,7 @@ import { AppEventManager, AppEvents } from "./common/app-events";
|
||||
import { render } from "react-dom";
|
||||
import { getCurrentHash, getCurrentPath, makeURL } from "./navigation";
|
||||
import Config from "./utils/config";
|
||||
import { isTesting } from "./utils/platform";
|
||||
|
||||
import { initalizeLogger, logger } from "./utils/logger";
|
||||
import { AuthProps } from "./views/auth";
|
||||
import { loadDatabase } from "./hooks/use-database";
|
||||
@@ -125,7 +125,7 @@ function fallbackRoute(): RouteWithPath {
|
||||
}
|
||||
|
||||
function redirectToRegistration(path: Routes): RouteWithPath<AuthProps> | null {
|
||||
if (!isTesting() && !shouldSkipInitiation() && !routes[path]) {
|
||||
if (!IS_TESTING && !shouldSkipInitiation() && !routes[path]) {
|
||||
window.history.replaceState({}, "", makeURL("/signup", getCurrentHash()));
|
||||
return { route: routes["/signup"], path: "/signup" };
|
||||
}
|
||||
@@ -156,8 +156,7 @@ async function renderApp() {
|
||||
} = getRoute();
|
||||
|
||||
if (serviceWorkerWhitelist.includes(path)) await initializeServiceWorker();
|
||||
if (import.meta.env.REACT_APP_PLATFORM === "desktop")
|
||||
await loadDatabase("db");
|
||||
if (IS_DESKTOP_APP) await loadDatabase("db");
|
||||
|
||||
logger.measure("app render");
|
||||
|
||||
@@ -174,7 +173,7 @@ async function renderApp() {
|
||||
}
|
||||
|
||||
async function initializeServiceWorker() {
|
||||
if (import.meta.env.REACT_APP_PLATFORM !== "desktop") {
|
||||
if (!IS_DESKTOP_APP) {
|
||||
logger.info("Initializing service worker...");
|
||||
const serviceWorker = await import("./service-worker-registration");
|
||||
|
||||
|
||||
@@ -19,11 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { INNCrypto } from "@notesnook/crypto/dist/src/interfaces";
|
||||
import CryptoWorker from "@notesnook/crypto-worker/dist/src/worker.js?worker";
|
||||
import { isDesktop } from "../utils/platform";
|
||||
|
||||
async function loadNNCrypto() {
|
||||
const hasWorker = "Worker" in window || "Worker" in global;
|
||||
if (isDesktop() && window.NativeNNCrypto) {
|
||||
if (IS_DESKTOP_APP && window.NativeNNCrypto) {
|
||||
return window.NativeNNCrypto;
|
||||
} else if (hasWorker) {
|
||||
const { NNCryptoWorker } = await import("@notesnook/crypto-worker");
|
||||
|
||||
@@ -29,6 +29,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://cra.link/PWA
|
||||
|
||||
type ServiceWorkerRegistrationConfig = {
|
||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
||||
onSuccess?: (registration: ServiceWorkerRegistration) => void;
|
||||
onError?: (error: Error) => void;
|
||||
};
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === "localhost" ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
@@ -39,13 +45,10 @@ const isLocalhost = Boolean(
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (
|
||||
import.meta.env.NODE_ENV === "production" &&
|
||||
"serviceWorker" in navigator
|
||||
) {
|
||||
export function register(config: ServiceWorkerRegistrationConfig) {
|
||||
if (import.meta.env.PROD && "serviceWorker" in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(import.meta.env.PUBLIC_URL, window.location.href);
|
||||
const publicUrl = new URL(PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
@@ -54,7 +57,7 @@ export function register(config) {
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const swUrl = `${import.meta.env.PUBLIC_URL}/service-worker.js`;
|
||||
const swUrl = `${PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
@@ -76,7 +79,10 @@ export function register(config) {
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
function registerValidSW(
|
||||
swUrl: string,
|
||||
config: ServiceWorkerRegistrationConfig
|
||||
) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
@@ -120,7 +126,10 @@ function registerValidSW(swUrl, config) {
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
function checkValidServiceWorker(
|
||||
swUrl: string,
|
||||
config: ServiceWorkerRegistrationConfig
|
||||
) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { "Service-Worker": "script" }
|
||||
@@ -16,14 +16,8 @@ GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-restricted-globals */
|
||||
// This service worker can be customized!
|
||||
// See https://developers.google.com/web/tools/workbox/modules
|
||||
// for the list of available Workbox modules, or add any other
|
||||
// code you'd like.
|
||||
// You can also remove this file if you'd prefer not to use a
|
||||
// service worker, and the Workbox build step will be skipped.
|
||||
/* eslint-disable no-var */
|
||||
/// <reference lib="webworker" />
|
||||
|
||||
import { clientsClaim } from "workbox-core";
|
||||
import { ExpirationPlugin } from "workbox-expiration";
|
||||
@@ -31,20 +25,17 @@ import { precacheAndRoute, createHandlerBoundToURL } from "workbox-precaching";
|
||||
import { registerRoute } from "workbox-routing";
|
||||
import { StaleWhileRevalidate } from "workbox-strategies";
|
||||
|
||||
declare var self: ServiceWorkerGlobalScope & typeof globalThis;
|
||||
|
||||
clientsClaim();
|
||||
|
||||
// Precache all of the assets generated by your build process.
|
||||
// Their URLs are injected into the manifest variable below.
|
||||
// This variable must be present somewhere in your service worker file,
|
||||
// even if you decide not to use precaching. See https://cra.link/PWA
|
||||
/**
|
||||
* @type {import("workbox-precaching/_types").PrecacheEntry[]}
|
||||
*/
|
||||
var precacheRoutes = self.__WB_MANIFEST;
|
||||
const precacheRoutes = self.__WB_MANIFEST;
|
||||
const filters = [/KaTeX/i, /hack/i, /code-lang-/i];
|
||||
precacheAndRoute(
|
||||
precacheRoutes.filter((route) => {
|
||||
return filters.every((filter) => !filter.test(route.url));
|
||||
return filters.every(
|
||||
(filter) => !filter.test(typeof route === "string" ? route : route.url)
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -70,7 +61,7 @@ registerRoute(
|
||||
|
||||
return true;
|
||||
},
|
||||
createHandlerBoundToURL(import.meta.env.PUBLIC_URL + "/index.html")
|
||||
createHandlerBoundToURL(PUBLIC_URL + "/index.html")
|
||||
);
|
||||
|
||||
// An example runtime caching route for requests that aren't handled by the
|
||||
@@ -101,12 +92,11 @@ self.addEventListener("message", (event) => {
|
||||
break;
|
||||
case "GET_VERSION":
|
||||
{
|
||||
const VERSION = import.meta.env.REACT_APP_VERSION;
|
||||
const HASH = import.meta.env.REACT_APP_GIT_HASH;
|
||||
if (!event.source) return;
|
||||
event.source.postMessage({
|
||||
type: data.type,
|
||||
version: VERSION,
|
||||
hash: HASH
|
||||
version: APP_VERSION,
|
||||
hash: GIT_HASH
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -25,7 +25,6 @@ import { isUserPremium } from "../hooks/use-is-user-premium";
|
||||
import { SUBSCRIPTION_STATUS } from "../common/constants";
|
||||
import { appVersion } from "../utils/version";
|
||||
import { findItemAndDelete } from "@notesnook/core/utils/array";
|
||||
import { isTesting } from "../utils/platform";
|
||||
|
||||
/**
|
||||
* @extends {BaseStore<AnnouncementStore>}
|
||||
@@ -35,7 +34,7 @@ class AnnouncementStore extends BaseStore {
|
||||
dialogAnnouncements = [];
|
||||
|
||||
refresh = async () => {
|
||||
if (isTesting()) return;
|
||||
if (IS_TESTING) return;
|
||||
|
||||
try {
|
||||
const inlineAnnouncements = [];
|
||||
@@ -77,7 +76,7 @@ export { useStore, store };
|
||||
|
||||
export const allowedPlatforms = [
|
||||
"all",
|
||||
import.meta.env.REACT_APP_PLATFORM,
|
||||
PLATFORM,
|
||||
...(window.os ? [window.os()] : [])
|
||||
];
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import { showReminderPreviewDialog } from "../common/dialog-controller";
|
||||
import dayjs from "dayjs";
|
||||
import Config from "../utils/config";
|
||||
import { store as notestore } from "./note-store";
|
||||
import { isDesktop, isTesting } from "../utils/platform";
|
||||
|
||||
import { desktop } from "../common/desktop-bridge";
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ async function resetReminders(reminders) {
|
||||
await TaskScheduler.stopAllWithPrefix("reminder:");
|
||||
|
||||
if (
|
||||
!isTesting() &&
|
||||
!IS_TESTING &&
|
||||
(!("Notification" in window) || Notification.permission !== "granted")
|
||||
)
|
||||
return;
|
||||
@@ -93,12 +93,12 @@ function scheduleReminder(id, reminder, cron) {
|
||||
return TaskScheduler.register(`reminder:${id}`, cron, async () => {
|
||||
if (!Config.get("reminderNotifications", true)) return;
|
||||
|
||||
if (isTesting()) {
|
||||
if (IS_TESTING) {
|
||||
window.confirm("Reminder activated!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDesktop()) {
|
||||
if (IS_DESKTOP_APP) {
|
||||
const tag = await desktop?.integration.showNotification.query({
|
||||
title: reminder.title,
|
||||
body: reminder.description,
|
||||
|
||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import CompressorWorker from "./compressor.worker.ts?worker";
|
||||
import type { Compressor as CompressorWorkerType } from "./compressor.worker";
|
||||
import { wrap, Remote } from "comlink";
|
||||
import { isDesktop } from "./platform";
|
||||
|
||||
import { desktop } from "../common/desktop-bridge";
|
||||
|
||||
export class Compressor {
|
||||
@@ -28,21 +28,21 @@ export class Compressor {
|
||||
private compressor!: Remote<CompressorWorkerType>;
|
||||
|
||||
constructor() {
|
||||
if (!isDesktop()) {
|
||||
if (!IS_DESKTOP_APP) {
|
||||
this.worker = new CompressorWorker();
|
||||
this.compressor = wrap<CompressorWorkerType>(this.worker);
|
||||
}
|
||||
}
|
||||
|
||||
async compress(data: string) {
|
||||
if (isDesktop())
|
||||
if (IS_DESKTOP_APP)
|
||||
return await desktop?.compress.gzip.query({ data, level: 6 });
|
||||
|
||||
return await this.compressor.gzip({ data, level: 6 });
|
||||
}
|
||||
|
||||
async decompress(data: string) {
|
||||
if (isDesktop()) return await desktop?.compress.gunzip.query(data);
|
||||
if (IS_DESKTOP_APP) return await desktop?.compress.gunzip.query(data);
|
||||
|
||||
return await this.compressor.gunzip({ data });
|
||||
}
|
||||
|
||||
@@ -122,10 +122,6 @@ export function getDownloadLink(platform: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function isDesktop() {
|
||||
return "os" in window || import.meta.env.REACT_APP_PLATFORM === "desktop";
|
||||
}
|
||||
|
||||
export function isMac() {
|
||||
return (
|
||||
getPlatform() === "macOS" || getPlatform() === "darwin" || isMacStoreApp()
|
||||
@@ -135,7 +131,3 @@ export function isMac() {
|
||||
export function isMacStoreApp() {
|
||||
return window.os && window.os() === "mas";
|
||||
}
|
||||
|
||||
export function isTesting() {
|
||||
return !!import.meta.env.REACT_APP_TEST;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import Config from "./config";
|
||||
|
||||
export function isTelemetryEnabled() {
|
||||
// telemetry is always disabled in DEBUG/TEST mode
|
||||
if (import.meta.env.NODE_ENV !== "production") return false;
|
||||
if (import.meta.env.DEV) return false;
|
||||
|
||||
return Config.get("telemetry", false);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { AppEventManager, AppEvents } from "../common/app-events";
|
||||
import { desktop } from "../common/desktop-bridge";
|
||||
import { isDesktop } from "./platform";
|
||||
import { appVersion, getServiceWorkerVersion } from "./version";
|
||||
|
||||
export async function checkForUpdate() {
|
||||
if (isDesktop()) await desktop?.updater.check.query();
|
||||
if (IS_DESKTOP_APP) await desktop?.updater.check.query();
|
||||
else {
|
||||
AppEventManager.publish(AppEvents.checkingForUpdate);
|
||||
|
||||
@@ -35,7 +34,11 @@ export async function checkForUpdate() {
|
||||
const workerVersion = await getServiceWorkerVersion(
|
||||
registration.waiting
|
||||
);
|
||||
if (!workerVersion || workerVersion.numerical <= appVersion.numerical) {
|
||||
if (
|
||||
!workerVersion ||
|
||||
workerVersion.numerical <= appVersion.numerical ||
|
||||
workerVersion.hash === appVersion.hash
|
||||
) {
|
||||
registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
||||
continue;
|
||||
}
|
||||
@@ -52,17 +55,21 @@ export async function checkForUpdate() {
|
||||
}
|
||||
|
||||
export async function downloadUpdate() {
|
||||
if (isDesktop()) await desktop?.updater.download.query();
|
||||
if (IS_DESKTOP_APP) await desktop?.updater.download.query();
|
||||
else {
|
||||
console.log("Force updating");
|
||||
if (!("serviceWorker" in navigator)) return;
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
await registration.update();
|
||||
try {
|
||||
if (!("serviceWorker" in navigator)) return;
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
await registration.update();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function installUpdate() {
|
||||
if (isDesktop()) await desktop?.updater.install.query();
|
||||
if (IS_DESKTOP_APP) await desktop?.updater.install.query();
|
||||
else {
|
||||
const registrations =
|
||||
(await navigator.serviceWorker?.getRegistrations()) || [];
|
||||
|
||||
@@ -20,15 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
export type Platforms = "web" | "desktop";
|
||||
export type AppVersion = typeof appVersion;
|
||||
export const appVersion = {
|
||||
formatted: format(
|
||||
import.meta.env.REACT_APP_VERSION,
|
||||
import.meta.env.REACT_APP_GIT_HASH,
|
||||
import.meta.env.REACT_APP_PLATFORM as Platforms,
|
||||
import.meta.env.REACT_APP_BETA === "true"
|
||||
),
|
||||
clean: formatVersion(import.meta.env.REACT_APP_VERSION),
|
||||
numerical: parseInt(import.meta.env.REACT_APP_VERSION || "0"),
|
||||
isBeta: import.meta.env.REACT_APP_BETA === "true"
|
||||
formatted: format(APP_VERSION, GIT_HASH, PLATFORM, IS_BETA),
|
||||
clean: formatVersion(APP_VERSION),
|
||||
numerical: parseInt(APP_VERSION || "0"),
|
||||
hash: GIT_HASH,
|
||||
isBeta: IS_BETA
|
||||
};
|
||||
|
||||
function format(
|
||||
@@ -59,11 +55,12 @@ export function getServiceWorkerVersion(
|
||||
if (type !== "GET_VERSION") return;
|
||||
clearTimeout(timeout);
|
||||
|
||||
const { version } = ev.data;
|
||||
const { version, hash } = ev.data;
|
||||
resolve({
|
||||
formatted: formatVersion(version),
|
||||
numerical: parseInt(version),
|
||||
clean: formatVersion(version),
|
||||
hash,
|
||||
isBeta: appVersion.isBeta
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ import useDatabase from "../hooks/use-database";
|
||||
import Loader from "../components/loader";
|
||||
import { showToast } from "../utils/toast";
|
||||
import AuthContainer from "../components/auth-container";
|
||||
import { isTesting } from "../utils/platform";
|
||||
|
||||
import { useTimer } from "../hooks/use-timer";
|
||||
import { AuthenticatorType } from "../dialogs/mfa/types";
|
||||
import {
|
||||
@@ -521,7 +521,7 @@ function AccountRecovery(props: BaseAuthComponentProps<"recover">) {
|
||||
|
||||
const url = await db.user?.recoverAccount(form.email.toLowerCase());
|
||||
console.log(url);
|
||||
if (isTesting()) {
|
||||
if (IS_TESTING) {
|
||||
window.open(url, "_self");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,128 +21,23 @@ import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
import svgrPlugin from "vite-plugin-svgr";
|
||||
import envCompatible from "vite-plugin-env-compatible";
|
||||
import { VitePWA, ManifestOptions } from "vite-plugin-pwa";
|
||||
import { VitePWA } from "vite-plugin-pwa";
|
||||
import autoprefixer from "autoprefixer";
|
||||
import { WEB_MANIFEST } from "./web-manifest";
|
||||
import { execSync } from "child_process";
|
||||
import { version } from "./package.json";
|
||||
|
||||
const WEB_MANIFEST: Partial<ManifestOptions> = {
|
||||
name: "Notesnook",
|
||||
description:
|
||||
"A fully open source & end-to-end encrypted note taking alternative to Evernote.",
|
||||
short_name: "Notesnook",
|
||||
shortcuts: [
|
||||
{
|
||||
name: "New note",
|
||||
url: "/#/notes/create",
|
||||
description: "Create a new note",
|
||||
icons: [
|
||||
{
|
||||
src: "/android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "New notebook",
|
||||
url: "/#/notebooks/create",
|
||||
description: "Create a new notebook",
|
||||
icons: [
|
||||
{
|
||||
src: "/android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
icons: [
|
||||
{
|
||||
src: "favicon-16x16.png",
|
||||
sizes: "16x16",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "favicon-32x32.png",
|
||||
sizes: "32x32",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "favicon-72x72.png",
|
||||
sizes: "72x72",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "/android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "/android-chrome-512x512.png",
|
||||
sizes: "512x512",
|
||||
type: "image/png"
|
||||
}
|
||||
],
|
||||
screenshots: [
|
||||
{
|
||||
src: "/screenshots/screenshot-1.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-2.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-3.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-4.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-5.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-6.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-7.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
}
|
||||
],
|
||||
related_applications: [
|
||||
{
|
||||
platform: "play",
|
||||
url: "https://play.google.com/store/apps/details?id=com.streetwriters.notesnook",
|
||||
id: "com.streetwriters.notesnook"
|
||||
},
|
||||
{
|
||||
platform: "itunes",
|
||||
url: "https://apps.apple.com/us/app/notesnook-private-notes-app/id1544027013"
|
||||
}
|
||||
],
|
||||
prefer_related_applications: true,
|
||||
orientation: "any",
|
||||
start_url: ".",
|
||||
theme_color: "#01c352",
|
||||
background_color: "#ffffff",
|
||||
display: "standalone",
|
||||
categories: ["productivity", "lifestyle", "education", "books"]
|
||||
};
|
||||
|
||||
const gitHash = (() => {
|
||||
try {
|
||||
return execSync("git rev-parse --short HEAD").toString().trim();
|
||||
} catch (e) {
|
||||
return process.env.GIT_HASH || "gitless";
|
||||
}
|
||||
})();
|
||||
const appVersion = version.replaceAll(".", "");
|
||||
const isTesting =
|
||||
process.env.REACT_APP_TEST === "true" ||
|
||||
process.env.NODE_ENV === "development";
|
||||
const isDesktop = process.env.REACT_APP_PLATFORM === "desktop";
|
||||
process.env.TEST === "true" || process.env.NODE_ENV === "development";
|
||||
const isDesktop = process.env.PLATFORM === "desktop";
|
||||
|
||||
export default defineConfig({
|
||||
envPrefix: "REACT_APP_",
|
||||
@@ -152,14 +47,23 @@ export default defineConfig({
|
||||
minify: "esbuild",
|
||||
cssMinify: true,
|
||||
emptyOutDir: true,
|
||||
sourcemap: process.env.GENERATE_SOURCEMAP === "true",
|
||||
sourcemap: isTesting,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
assetFileNames: "assets/[name]-[hash:12][extname]",
|
||||
chunkFileNames: "[name]-[hash:12].js"
|
||||
chunkFileNames: "assets/[name]-[hash:12].js"
|
||||
}
|
||||
}
|
||||
},
|
||||
define: {
|
||||
GIT_HASH: `"${gitHash}"`,
|
||||
APP_VERSION: `"${appVersion}"`,
|
||||
PUBLIC_URL: `"${process.env.PUBLIC_URL || ""}"`,
|
||||
IS_DESKTOP_APP: isDesktop,
|
||||
PLATFORM: `"${process.env.PLATFORM}"`,
|
||||
IS_TESTING: process.env.TEST === "true",
|
||||
IS_BETA: process.env.BETA === "true"
|
||||
},
|
||||
logLevel: process.env.NODE_ENV === "production" ? "warn" : "info",
|
||||
resolve: {
|
||||
dedupe: ["react", "react-dom", "@mdi/js", "@mdi/react", "@emotion/react"],
|
||||
@@ -194,7 +98,7 @@ export default defineConfig({
|
||||
manifest: WEB_MANIFEST,
|
||||
injectRegister: null,
|
||||
srcDir: "src",
|
||||
filename: "service-worker.js"
|
||||
filename: "service-worker.ts"
|
||||
})
|
||||
]),
|
||||
react({
|
||||
|
||||
135
apps/web/web-manifest.ts
Normal file
135
apps/web/web-manifest.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ManifestOptions } from "vite-plugin-pwa";
|
||||
|
||||
export const WEB_MANIFEST: Partial<ManifestOptions> = {
|
||||
name: "Notesnook",
|
||||
description:
|
||||
"A fully open source & end-to-end encrypted note taking alternative to Evernote.",
|
||||
short_name: "Notesnook",
|
||||
shortcuts: [
|
||||
{
|
||||
name: "New note",
|
||||
url: "/#/notes/create",
|
||||
description: "Create a new note",
|
||||
icons: [
|
||||
{
|
||||
src: "/android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "New notebook",
|
||||
url: "/#/notebooks/create",
|
||||
description: "Create a new notebook",
|
||||
icons: [
|
||||
{
|
||||
src: "/android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
icons: [
|
||||
{
|
||||
src: "favicon-16x16.png",
|
||||
sizes: "16x16",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "favicon-32x32.png",
|
||||
sizes: "32x32",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "favicon-72x72.png",
|
||||
sizes: "72x72",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "/android-chrome-192x192.png",
|
||||
sizes: "192x192",
|
||||
type: "image/png"
|
||||
},
|
||||
{
|
||||
src: "/android-chrome-512x512.png",
|
||||
sizes: "512x512",
|
||||
type: "image/png"
|
||||
}
|
||||
],
|
||||
screenshots: [
|
||||
{
|
||||
src: "/screenshots/screenshot-1.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-2.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-3.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-4.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-5.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-6.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
},
|
||||
{
|
||||
src: "/screenshots/screenshot-7.jpg",
|
||||
sizes: "1080x1920",
|
||||
type: "image/jpeg"
|
||||
}
|
||||
],
|
||||
related_applications: [
|
||||
{
|
||||
platform: "play",
|
||||
url: "https://play.google.com/store/apps/details?id=com.streetwriters.notesnook",
|
||||
id: "com.streetwriters.notesnook"
|
||||
},
|
||||
{
|
||||
platform: "itunes",
|
||||
url: "https://apps.apple.com/us/app/notesnook-private-notes-app/id1544027013"
|
||||
}
|
||||
],
|
||||
prefer_related_applications: true,
|
||||
orientation: "any",
|
||||
start_url: ".",
|
||||
theme_color: "#01c352",
|
||||
background_color: "#ffffff",
|
||||
display: "standalone",
|
||||
categories: ["productivity", "lifestyle", "education", "books"]
|
||||
};
|
||||
Reference in New Issue
Block a user