fix: configurable changelog url (#2418)

This commit is contained in:
Peng Xiao 2023-05-18 07:16:22 +08:00 committed by GitHub
parent 53c4fc6dfa
commit f875b37641
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 94 additions and 73 deletions

View File

@ -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 () => {

View File

@ -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',
};

View File

@ -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

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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 />

View File

@ -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 {

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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];

View File

@ -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';

View File

@ -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';

View File

@ -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({

View File

@ -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();
}}
>

View File

@ -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({

View File

@ -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);
}
}