mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-11-24 11:24:08 +03:00
fix: configurable changelog url (#2418)
This commit is contained in:
parent
53c4fc6dfa
commit
f875b37641
@ -3,6 +3,7 @@ import { app, Menu } from 'electron';
|
||||
import { isMacOS } from '../../utils';
|
||||
import { subjects } from './events';
|
||||
import { checkForUpdatesAndNotify } from './handlers/updater';
|
||||
import { revealLogFile } from './logger';
|
||||
|
||||
// Unique id for menuitems
|
||||
const MENUITEM_NEW_PAGE = 'affine:new-page';
|
||||
@ -115,6 +116,12 @@ export function createApplicationMenu() {
|
||||
await shell.openExternal('https://affine.pro/');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Open logs folder',
|
||||
click: async () => {
|
||||
revealLogFile();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Check for Updates',
|
||||
click: async () => {
|
||||
|
@ -33,4 +33,7 @@ export const buildFlags = {
|
||||
enableDebugPage: Boolean(
|
||||
process.env.ENABLE_DEBUG_PAGE ?? process.env.NODE_ENV === 'development'
|
||||
),
|
||||
changelogUrl:
|
||||
process.env.CHANGELOG_URL ??
|
||||
'https://affine.pro/blog/whats-new-affine-0518',
|
||||
};
|
||||
|
@ -1,52 +1,19 @@
|
||||
import type {
|
||||
QueryParamError,
|
||||
Unreachable,
|
||||
WorkspaceNotFoundError,
|
||||
} from '@affine/env/constant';
|
||||
import { PageNotFoundError } from '@affine/env/constant';
|
||||
import { RequestError } from '@affine/workspace/affine/api';
|
||||
import type { NextRouter } from 'next/router';
|
||||
import type { ErrorInfo, ReactNode } from 'react';
|
||||
import type React from 'react';
|
||||
import { Component } from 'react';
|
||||
|
||||
import type { BlockSuiteWorkspace } from '../../shared';
|
||||
|
||||
export type AffineErrorBoundaryProps = React.PropsWithChildren<{
|
||||
router: NextRouter;
|
||||
}>;
|
||||
|
||||
export class PageNotFoundError extends TypeError {
|
||||
readonly workspace: BlockSuiteWorkspace;
|
||||
readonly pageId: string;
|
||||
|
||||
constructor(workspace: BlockSuiteWorkspace, pageId: string) {
|
||||
super();
|
||||
this.workspace = workspace;
|
||||
this.pageId = pageId;
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceNotFoundError extends TypeError {
|
||||
readonly workspaceId: string;
|
||||
|
||||
constructor(workspaceId: string) {
|
||||
super();
|
||||
this.workspaceId = workspaceId;
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryParamError extends TypeError {
|
||||
readonly targetKey: string;
|
||||
readonly query: unknown;
|
||||
|
||||
constructor(targetKey: string, query: unknown) {
|
||||
super();
|
||||
this.targetKey = targetKey;
|
||||
this.query = query;
|
||||
}
|
||||
}
|
||||
|
||||
export class Unreachable extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
type AffineError =
|
||||
| QueryParamError
|
||||
| Unreachable
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Button, IconButton, Menu, MenuItem, Wrapper } from '@affine/component';
|
||||
import { config } from '@affine/env';
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { PermissionType } from '@affine/workspace/affine/api';
|
||||
import type {
|
||||
@ -17,7 +18,6 @@ import { useCallback, useState } from 'react';
|
||||
|
||||
import { useMembers } from '../../../../../hooks/affine/use-members';
|
||||
import { toast } from '../../../../../utils';
|
||||
import { Unreachable } from '../../../affine-error-eoundary';
|
||||
import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal';
|
||||
import { TransformWorkspaceToAffineModal } from '../../../transform-workspace-to-affine-modal';
|
||||
import type { PanelProps } from '../../index';
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
Wrapper,
|
||||
} from '@affine/component';
|
||||
import { config } from '@affine/env';
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type {
|
||||
AffineLegacyCloudWorkspace,
|
||||
@ -19,7 +20,6 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import { useToggleWorkspacePublish } from '../../../../../hooks/affine/use-toggle-workspace-publish';
|
||||
import type { AffineOfficialWorkspace } from '../../../../../shared';
|
||||
import { toast } from '../../../../../utils';
|
||||
import { Unreachable } from '../../../affine-error-eoundary';
|
||||
import { EnableAffineCloudModal } from '../../../enable-affine-cloud-modal';
|
||||
import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal';
|
||||
import type { WorkspaceSettingDetailProps } from '../../index';
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ShareMenu } from '@affine/component/share-menu';
|
||||
import { config } from '@affine/env';
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import type {
|
||||
AffineLegacyCloudWorkspace,
|
||||
LocalWorkspace,
|
||||
@ -15,7 +16,6 @@ import { useToggleWorkspacePublish } from '../../../../hooks/affine/use-toggle-w
|
||||
import { useOnTransformWorkspace } from '../../../../hooks/root/use-on-transform-workspace';
|
||||
import { useRouterHelper } from '../../../../hooks/use-router-helper';
|
||||
import { WorkspaceSubPath } from '../../../../shared';
|
||||
import { Unreachable } from '../../../affine/affine-error-eoundary';
|
||||
import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal';
|
||||
import type { BaseHeaderProps } from '../header';
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { PageNotFoundError } from '@affine/env/constant';
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
@ -11,7 +12,6 @@ import { startTransition, useCallback } from 'react';
|
||||
|
||||
import { currentEditorAtom, workspacePreferredModeAtom } from '../atoms';
|
||||
import type { AffineOfficialWorkspace } from '../shared';
|
||||
import { PageNotFoundError } from './affine/affine-error-eoundary';
|
||||
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
|
||||
import { WorkspaceHeader } from './blocksuite/workspace-header';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { MuiFade, Tooltip } from '@affine/component';
|
||||
import { getEnvironment } from '@affine/env';
|
||||
import { config, getEnvironment } from '@affine/env';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CloseIcon, NewIcon } from '@blocksuite/icons';
|
||||
import { useAtom } from 'jotai';
|
||||
@ -74,10 +74,7 @@ export const HelpIsland = ({
|
||||
<StyledIconWrapper
|
||||
data-testid="right-bottom-change-log-icon"
|
||||
onClick={() => {
|
||||
window.open(
|
||||
'https://github.com/toeverything/AFFiNE/releases',
|
||||
'_blank'
|
||||
);
|
||||
window.open(config.changelogUrl, '_blank');
|
||||
}}
|
||||
>
|
||||
<NewIcon />
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Breadcrumbs, IconButton, ListSkeleton } from '@affine/component';
|
||||
import { StyledTableContainer } from '@affine/component/page-list';
|
||||
import { QueryParamError } from '@affine/env/constant';
|
||||
import { SearchIcon } from '@blocksuite/icons';
|
||||
import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
|
||||
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
||||
@ -13,7 +14,6 @@ import {
|
||||
publicWorkspaceAtom,
|
||||
publicWorkspaceIdAtom,
|
||||
} from '../../atoms/public-workspace';
|
||||
import { QueryParamError } from '../../components/affine/affine-error-eoundary';
|
||||
import { WorkspaceAvatar } from '../../components/pure/footer';
|
||||
import { PageLoading } from '../../components/pure/loading';
|
||||
import {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
|
||||
import type { BlockSuiteFeatureFlags } from '@affine/env';
|
||||
import { config } from '@affine/env';
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { rootCurrentPageIdAtom } from '@affine/workspace/atom';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
@ -15,7 +16,6 @@ import type React from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { rootCurrentWorkspaceAtom } from '../../../atoms/root';
|
||||
import { Unreachable } from '../../../components/affine/affine-error-eoundary';
|
||||
import { useReferenceLinkEffect } from '../../../hooks/affine/use-reference-link-effect';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { usePinboardHandler } from '../../../hooks/use-pinboard-handler';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { QueryParamError, Unreachable } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { FolderIcon } from '@blocksuite/icons';
|
||||
@ -6,10 +7,6 @@ import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import {
|
||||
QueryParamError,
|
||||
Unreachable,
|
||||
} from '../../../components/affine/affine-error-eoundary';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
|
||||
import type { SettingPanel } from '@affine/workspace/type';
|
||||
@ -15,7 +16,6 @@ import type { NextRouter } from 'next/router';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
|
||||
import { Unreachable } from '../../../components/affine/affine-error-eoundary';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { rootStore } from '@affine/workspace/atom';
|
||||
import type { AffineLegacyCloudWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
@ -6,7 +7,6 @@ import { assertExists } from '@blocksuite/store';
|
||||
|
||||
import { workspacesAtom } from '../../atoms';
|
||||
import { createAffineProviders } from '../../blocksuite';
|
||||
import { Unreachable } from '../../components/affine/affine-error-eoundary';
|
||||
import { affineApis } from '../../shared/apis';
|
||||
|
||||
type Query = (typeof QueryKey)[keyof typeof QueryKey];
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { AFFINE_STORAGE_KEY, config, prefixUrl } from '@affine/env';
|
||||
import { initPage } from '@affine/env/blocksuite';
|
||||
import { PageNotFoundError } from '@affine/env/constant';
|
||||
import { currentAffineUserAtom } from '@affine/workspace/affine/atom';
|
||||
import {
|
||||
clearLoginStorage,
|
||||
@ -30,7 +31,6 @@ import { z } from 'zod';
|
||||
|
||||
import { createAffineProviders } from '../../blocksuite';
|
||||
import { createAffineDownloadProvider } from '../../blocksuite/providers/affine';
|
||||
import { PageNotFoundError } from '../../components/affine/affine-error-eoundary';
|
||||
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
|
||||
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
|
||||
import { PageDetailEditor } from '../../components/page-detail-editor';
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
DEFAULT_WORKSPACE_NAME,
|
||||
} from '@affine/env';
|
||||
import { initPage } from '@affine/env/blocksuite';
|
||||
import { PageNotFoundError } from '@affine/env/constant';
|
||||
import {
|
||||
CRUD,
|
||||
saveWorkspaceToLocalStorage,
|
||||
@ -18,7 +19,6 @@ import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
import React from 'react';
|
||||
|
||||
import { PageNotFoundError } from '../../components/affine/affine-error-eoundary';
|
||||
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
|
||||
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
|
||||
import { PageDetailEditor } from '../../components/page-detail-editor';
|
||||
|
@ -13,6 +13,12 @@ export const root = style({
|
||||
userSelect: 'none',
|
||||
cursor: 'pointer',
|
||||
padding: '0 24px',
|
||||
transition: 'background 0.2s ease',
|
||||
selectors: {
|
||||
'&:active': {
|
||||
background: 'var(--affine-white-40)',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const icon = style({
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { config } from '@affine/env/config';
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CloseIcon, NewIcon, ResetIcon } from '@blocksuite/icons';
|
||||
import clsx from 'clsx';
|
||||
@ -46,18 +48,11 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
const updateAvailable = useAtomValue(updateAvailableAtom);
|
||||
const currentVersion = useAtomValue(currentVersionAtom);
|
||||
const downloadProgress = useAtomValue(downloadProgressAtom);
|
||||
const onReadOrDismissChangelog = useSetAtom(changelogCheckedAtom);
|
||||
|
||||
const onReadOrDismissCurrentChangelog = (visit: boolean) => {
|
||||
if (visit) {
|
||||
window.open(
|
||||
`https://github.com/toeverything/AFFiNE/releases/tag/v${currentVersion}`,
|
||||
'_blank'
|
||||
);
|
||||
}
|
||||
const setChangelogCheckAtom = useSetAtom(changelogCheckedAtom);
|
||||
|
||||
const onDismissCurrentChangelog = () => {
|
||||
startTransition(() =>
|
||||
onReadOrDismissChangelog(mapping => {
|
||||
setChangelogCheckAtom(mapping => {
|
||||
return {
|
||||
...mapping,
|
||||
[currentVersion!]: true,
|
||||
@ -79,10 +74,19 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
onClick={() => {
|
||||
if (updateReady) {
|
||||
window.apis?.updater.quitAndInstall();
|
||||
} else if (updateAvailable?.allowAutoUpdate) {
|
||||
// wait for download to finish
|
||||
} else if (updateAvailable || currentChangelogUnread) {
|
||||
onReadOrDismissCurrentChangelog(true);
|
||||
} else if (updateAvailable) {
|
||||
if (updateAvailable.allowAutoUpdate) {
|
||||
// wait for download to finish
|
||||
} else {
|
||||
window.open(
|
||||
`https://github.com/toeverything/AFFiNE/releases/tag/v${currentVersion}`,
|
||||
'_blank'
|
||||
);
|
||||
}
|
||||
} else if (currentChangelogUnread) {
|
||||
window.open(config.changelogUrl, '_blank');
|
||||
} else {
|
||||
throw new Unreachable();
|
||||
}
|
||||
}}
|
||||
>
|
||||
@ -155,7 +159,7 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
<div
|
||||
className={styles.closeIcon}
|
||||
onClick={e => {
|
||||
onReadOrDismissCurrentChangelog(false);
|
||||
onDismissCurrentChangelog();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
|
1
packages/env/src/config.ts
vendored
1
packages/env/src/config.ts
vendored
@ -11,6 +11,7 @@ export const buildFlagsSchema = z.object({
|
||||
enableBroadCastChannelProvider: z.boolean(),
|
||||
enableDebugPage: z.boolean(),
|
||||
enableLegacyCloud: z.boolean(),
|
||||
changelogUrl: z.string(),
|
||||
});
|
||||
|
||||
export const blockSuiteFeatureFlags = z.object({
|
||||
|
39
packages/env/src/constant.ts
vendored
39
packages/env/src/constant.ts
vendored
@ -1,3 +1,5 @@
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
|
||||
export const AFFINE_STORAGE_KEY = 'affine-local-storage-v2';
|
||||
export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace';
|
||||
export const UNTITLED_WORKSPACE_NAME = 'Untitled';
|
||||
@ -76,3 +78,40 @@ export const Messages = {
|
||||
message: string;
|
||||
};
|
||||
};
|
||||
|
||||
export class PageNotFoundError extends TypeError {
|
||||
readonly workspace: Workspace;
|
||||
readonly pageId: string;
|
||||
|
||||
constructor(workspace: Workspace, pageId: string) {
|
||||
super();
|
||||
this.workspace = workspace;
|
||||
this.pageId = pageId;
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceNotFoundError extends TypeError {
|
||||
readonly workspaceId: string;
|
||||
|
||||
constructor(workspaceId: string) {
|
||||
super();
|
||||
this.workspaceId = workspaceId;
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryParamError extends TypeError {
|
||||
readonly targetKey: string;
|
||||
readonly query: unknown;
|
||||
|
||||
constructor(targetKey: string, query: unknown) {
|
||||
super();
|
||||
this.targetKey = targetKey;
|
||||
this.query = query;
|
||||
}
|
||||
}
|
||||
|
||||
export class Unreachable extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user