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
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 { isMacOS } from '../../utils';
import { subjects } from './events'; import { subjects } from './events';
import { checkForUpdatesAndNotify } from './handlers/updater'; import { checkForUpdatesAndNotify } from './handlers/updater';
import { revealLogFile } from './logger';
// Unique id for menuitems // Unique id for menuitems
const MENUITEM_NEW_PAGE = 'affine:new-page'; const MENUITEM_NEW_PAGE = 'affine:new-page';
@@ -115,6 +116,12 @@ export function createApplicationMenu() {
await shell.openExternal('https://affine.pro/'); await shell.openExternal('https://affine.pro/');
}, },
}, },
{
label: 'Open logs folder',
click: async () => {
revealLogFile();
},
},
{ {
label: 'Check for Updates', label: 'Check for Updates',
click: async () => { click: async () => {

View File

@@ -33,4 +33,7 @@ export const buildFlags = {
enableDebugPage: Boolean( enableDebugPage: Boolean(
process.env.ENABLE_DEBUG_PAGE ?? process.env.NODE_ENV === 'development' 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 { RequestError } from '@affine/workspace/affine/api';
import type { NextRouter } from 'next/router'; import type { NextRouter } from 'next/router';
import type { ErrorInfo, ReactNode } from 'react'; import type { ErrorInfo, ReactNode } from 'react';
import type React from 'react'; import type React from 'react';
import { Component } from 'react'; import { Component } from 'react';
import type { BlockSuiteWorkspace } from '../../shared';
export type AffineErrorBoundaryProps = React.PropsWithChildren<{ export type AffineErrorBoundaryProps = React.PropsWithChildren<{
router: NextRouter; 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 = type AffineError =
| QueryParamError | QueryParamError
| Unreachable | Unreachable

View File

@@ -1,5 +1,6 @@
import { Button, IconButton, Menu, MenuItem, Wrapper } from '@affine/component'; import { Button, IconButton, Menu, MenuItem, Wrapper } from '@affine/component';
import { config } from '@affine/env'; import { config } from '@affine/env';
import { Unreachable } from '@affine/env/constant';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { PermissionType } from '@affine/workspace/affine/api'; import { PermissionType } from '@affine/workspace/affine/api';
import type { import type {
@@ -17,7 +18,6 @@ import { useCallback, useState } from 'react';
import { useMembers } from '../../../../../hooks/affine/use-members'; import { useMembers } from '../../../../../hooks/affine/use-members';
import { toast } from '../../../../../utils'; import { toast } from '../../../../../utils';
import { Unreachable } from '../../../affine-error-eoundary';
import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal'; import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal';
import { TransformWorkspaceToAffineModal } from '../../../transform-workspace-to-affine-modal'; import { TransformWorkspaceToAffineModal } from '../../../transform-workspace-to-affine-modal';
import type { PanelProps } from '../../index'; import type { PanelProps } from '../../index';

View File

@@ -6,6 +6,7 @@ import {
Wrapper, Wrapper,
} from '@affine/component'; } from '@affine/component';
import { config } from '@affine/env'; import { config } from '@affine/env';
import { Unreachable } from '@affine/env/constant';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { import type {
AffineLegacyCloudWorkspace, AffineLegacyCloudWorkspace,
@@ -19,7 +20,6 @@ import { useCallback, useEffect, useState } from 'react';
import { useToggleWorkspacePublish } from '../../../../../hooks/affine/use-toggle-workspace-publish'; import { useToggleWorkspacePublish } from '../../../../../hooks/affine/use-toggle-workspace-publish';
import type { AffineOfficialWorkspace } from '../../../../../shared'; import type { AffineOfficialWorkspace } from '../../../../../shared';
import { toast } from '../../../../../utils'; import { toast } from '../../../../../utils';
import { Unreachable } from '../../../affine-error-eoundary';
import { EnableAffineCloudModal } from '../../../enable-affine-cloud-modal'; import { EnableAffineCloudModal } from '../../../enable-affine-cloud-modal';
import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal'; import { TmpDisableAffineCloudModal } from '../../../tmp-disable-affine-cloud-modal';
import type { WorkspaceSettingDetailProps } from '../../index'; import type { WorkspaceSettingDetailProps } from '../../index';

View File

@@ -1,5 +1,6 @@
import { ShareMenu } from '@affine/component/share-menu'; import { ShareMenu } from '@affine/component/share-menu';
import { config } from '@affine/env'; import { config } from '@affine/env';
import { Unreachable } from '@affine/env/constant';
import type { import type {
AffineLegacyCloudWorkspace, AffineLegacyCloudWorkspace,
LocalWorkspace, LocalWorkspace,
@@ -15,7 +16,6 @@ import { useToggleWorkspacePublish } from '../../../../hooks/affine/use-toggle-w
import { useOnTransformWorkspace } from '../../../../hooks/root/use-on-transform-workspace'; import { useOnTransformWorkspace } from '../../../../hooks/root/use-on-transform-workspace';
import { useRouterHelper } from '../../../../hooks/use-router-helper'; import { useRouterHelper } from '../../../../hooks/use-router-helper';
import { WorkspaceSubPath } from '../../../../shared'; import { WorkspaceSubPath } from '../../../../shared';
import { Unreachable } from '../../../affine/affine-error-eoundary';
import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal'; import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal';
import type { BaseHeaderProps } from '../header'; 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 { EditorContainer } from '@blocksuite/editor';
import type { Page } from '@blocksuite/store'; import type { Page } from '@blocksuite/store';
import { assertExists } from '@blocksuite/store'; import { assertExists } from '@blocksuite/store';
@@ -11,7 +12,6 @@ import { startTransition, useCallback } from 'react';
import { currentEditorAtom, workspacePreferredModeAtom } from '../atoms'; import { currentEditorAtom, workspacePreferredModeAtom } from '../atoms';
import type { AffineOfficialWorkspace } from '../shared'; import type { AffineOfficialWorkspace } from '../shared';
import { PageNotFoundError } from './affine/affine-error-eoundary';
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor'; import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
import { WorkspaceHeader } from './blocksuite/workspace-header'; import { WorkspaceHeader } from './blocksuite/workspace-header';

View File

@@ -1,5 +1,5 @@
import { MuiFade, Tooltip } from '@affine/component'; import { MuiFade, Tooltip } from '@affine/component';
import { getEnvironment } from '@affine/env'; import { config, getEnvironment } from '@affine/env';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { CloseIcon, NewIcon } from '@blocksuite/icons'; import { CloseIcon, NewIcon } from '@blocksuite/icons';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
@@ -74,10 +74,7 @@ export const HelpIsland = ({
<StyledIconWrapper <StyledIconWrapper
data-testid="right-bottom-change-log-icon" data-testid="right-bottom-change-log-icon"
onClick={() => { onClick={() => {
window.open( window.open(config.changelogUrl, '_blank');
'https://github.com/toeverything/AFFiNE/releases',
'_blank'
);
}} }}
> >
<NewIcon /> <NewIcon />

View File

@@ -1,5 +1,6 @@
import { Breadcrumbs, IconButton, ListSkeleton } from '@affine/component'; import { Breadcrumbs, IconButton, ListSkeleton } from '@affine/component';
import { StyledTableContainer } from '@affine/component/page-list'; import { StyledTableContainer } from '@affine/component/page-list';
import { QueryParamError } from '@affine/env/constant';
import { SearchIcon } from '@blocksuite/icons'; import { SearchIcon } from '@blocksuite/icons';
import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url'; import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
@@ -13,7 +14,6 @@ import {
publicWorkspaceAtom, publicWorkspaceAtom,
publicWorkspaceIdAtom, publicWorkspaceIdAtom,
} from '../../atoms/public-workspace'; } from '../../atoms/public-workspace';
import { QueryParamError } from '../../components/affine/affine-error-eoundary';
import { WorkspaceAvatar } from '../../components/pure/footer'; import { WorkspaceAvatar } from '../../components/pure/footer';
import { PageLoading } from '../../components/pure/loading'; import { PageLoading } from '../../components/pure/loading';
import { import {

View File

@@ -1,6 +1,7 @@
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton'; import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
import type { BlockSuiteFeatureFlags } from '@affine/env'; import type { BlockSuiteFeatureFlags } from '@affine/env';
import { config } from '@affine/env'; import { config } from '@affine/env';
import { Unreachable } from '@affine/env/constant';
import { rootCurrentPageIdAtom } from '@affine/workspace/atom'; import { rootCurrentPageIdAtom } from '@affine/workspace/atom';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { assertExists } from '@blocksuite/store'; import { assertExists } from '@blocksuite/store';
@@ -15,7 +16,6 @@ import type React from 'react';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
import { rootCurrentWorkspaceAtom } from '../../../atoms/root'; import { rootCurrentWorkspaceAtom } from '../../../atoms/root';
import { Unreachable } from '../../../components/affine/affine-error-eoundary';
import { useReferenceLinkEffect } from '../../../hooks/affine/use-reference-link-effect'; import { useReferenceLinkEffect } from '../../../hooks/affine/use-reference-link-effect';
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace'; import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
import { usePinboardHandler } from '../../../hooks/use-pinboard-handler'; 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 { useAFFiNEI18N } from '@affine/i18n/hooks';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { FolderIcon } from '@blocksuite/icons'; import { FolderIcon } from '@blocksuite/icons';
@@ -6,10 +7,6 @@ import Head from 'next/head';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import {
QueryParamError,
Unreachable,
} from '../../../components/affine/affine-error-eoundary';
import { PageLoading } from '../../../components/pure/loading'; import { PageLoading } from '../../../components/pure/loading';
import { WorkspaceTitle } from '../../../components/pure/workspace-title'; import { WorkspaceTitle } from '../../../components/pure/workspace-title';
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace'; 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 { useAFFiNEI18N } from '@affine/i18n/hooks';
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import type { SettingPanel } from '@affine/workspace/type'; import type { SettingPanel } from '@affine/workspace/type';
@@ -15,7 +16,6 @@ import type { NextRouter } from 'next/router';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useCallback, useEffect } from 'react'; import React, { useCallback, useEffect } from 'react';
import { Unreachable } from '../../../components/affine/affine-error-eoundary';
import { PageLoading } from '../../../components/pure/loading'; import { PageLoading } from '../../../components/pure/loading';
import { WorkspaceTitle } from '../../../components/pure/workspace-title'; import { WorkspaceTitle } from '../../../components/pure/workspace-title';
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace'; 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 { rootStore } from '@affine/workspace/atom';
import type { AffineLegacyCloudWorkspace } from '@affine/workspace/type'; import type { AffineLegacyCloudWorkspace } from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
@@ -6,7 +7,6 @@ import { assertExists } from '@blocksuite/store';
import { workspacesAtom } from '../../atoms'; import { workspacesAtom } from '../../atoms';
import { createAffineProviders } from '../../blocksuite'; import { createAffineProviders } from '../../blocksuite';
import { Unreachable } from '../../components/affine/affine-error-eoundary';
import { affineApis } from '../../shared/apis'; import { affineApis } from '../../shared/apis';
type Query = (typeof QueryKey)[keyof typeof QueryKey]; type Query = (typeof QueryKey)[keyof typeof QueryKey];

View File

@@ -1,5 +1,6 @@
import { AFFINE_STORAGE_KEY, config, prefixUrl } from '@affine/env'; import { AFFINE_STORAGE_KEY, config, prefixUrl } from '@affine/env';
import { initPage } from '@affine/env/blocksuite'; import { initPage } from '@affine/env/blocksuite';
import { PageNotFoundError } from '@affine/env/constant';
import { currentAffineUserAtom } from '@affine/workspace/affine/atom'; import { currentAffineUserAtom } from '@affine/workspace/affine/atom';
import { import {
clearLoginStorage, clearLoginStorage,
@@ -30,7 +31,6 @@ import { z } from 'zod';
import { createAffineProviders } from '../../blocksuite'; import { createAffineProviders } from '../../blocksuite';
import { createAffineDownloadProvider } from '../../blocksuite/providers/affine'; import { createAffineDownloadProvider } from '../../blocksuite/providers/affine';
import { PageNotFoundError } from '../../components/affine/affine-error-eoundary';
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail'; import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list'; import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
import { PageDetailEditor } from '../../components/page-detail-editor'; import { PageDetailEditor } from '../../components/page-detail-editor';

View File

@@ -4,6 +4,7 @@ import {
DEFAULT_WORKSPACE_NAME, DEFAULT_WORKSPACE_NAME,
} from '@affine/env'; } from '@affine/env';
import { initPage } from '@affine/env/blocksuite'; import { initPage } from '@affine/env/blocksuite';
import { PageNotFoundError } from '@affine/env/constant';
import { import {
CRUD, CRUD,
saveWorkspaceToLocalStorage, saveWorkspaceToLocalStorage,
@@ -18,7 +19,6 @@ import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
import { nanoid } from '@blocksuite/store'; import { nanoid } from '@blocksuite/store';
import React from 'react'; import React from 'react';
import { PageNotFoundError } from '../../components/affine/affine-error-eoundary';
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail'; import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list'; import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
import { PageDetailEditor } from '../../components/page-detail-editor'; import { PageDetailEditor } from '../../components/page-detail-editor';

View File

@@ -13,6 +13,12 @@ export const root = style({
userSelect: 'none', userSelect: 'none',
cursor: 'pointer', cursor: 'pointer',
padding: '0 24px', padding: '0 24px',
transition: 'background 0.2s ease',
selectors: {
'&:active': {
background: 'var(--affine-white-40)',
},
},
}); });
export const icon = style({ 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 { useAFFiNEI18N } from '@affine/i18n/hooks';
import { CloseIcon, NewIcon, ResetIcon } from '@blocksuite/icons'; import { CloseIcon, NewIcon, ResetIcon } from '@blocksuite/icons';
import clsx from 'clsx'; import clsx from 'clsx';
@@ -46,18 +48,11 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
const updateAvailable = useAtomValue(updateAvailableAtom); const updateAvailable = useAtomValue(updateAvailableAtom);
const currentVersion = useAtomValue(currentVersionAtom); const currentVersion = useAtomValue(currentVersionAtom);
const downloadProgress = useAtomValue(downloadProgressAtom); const downloadProgress = useAtomValue(downloadProgressAtom);
const onReadOrDismissChangelog = useSetAtom(changelogCheckedAtom); const setChangelogCheckAtom = useSetAtom(changelogCheckedAtom);
const onReadOrDismissCurrentChangelog = (visit: boolean) => {
if (visit) {
window.open(
`https://github.com/toeverything/AFFiNE/releases/tag/v${currentVersion}`,
'_blank'
);
}
const onDismissCurrentChangelog = () => {
startTransition(() => startTransition(() =>
onReadOrDismissChangelog(mapping => { setChangelogCheckAtom(mapping => {
return { return {
...mapping, ...mapping,
[currentVersion!]: true, [currentVersion!]: true,
@@ -79,10 +74,19 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
onClick={() => { onClick={() => {
if (updateReady) { if (updateReady) {
window.apis?.updater.quitAndInstall(); window.apis?.updater.quitAndInstall();
} else if (updateAvailable?.allowAutoUpdate) { } else if (updateAvailable) {
if (updateAvailable.allowAutoUpdate) {
// wait for download to finish // wait for download to finish
} else if (updateAvailable || currentChangelogUnread) { } else {
onReadOrDismissCurrentChangelog(true); 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 <div
className={styles.closeIcon} className={styles.closeIcon}
onClick={e => { onClick={e => {
onReadOrDismissCurrentChangelog(false); onDismissCurrentChangelog();
e.stopPropagation(); e.stopPropagation();
}} }}
> >

View File

@@ -11,6 +11,7 @@ export const buildFlagsSchema = z.object({
enableBroadCastChannelProvider: z.boolean(), enableBroadCastChannelProvider: z.boolean(),
enableDebugPage: z.boolean(), enableDebugPage: z.boolean(),
enableLegacyCloud: z.boolean(), enableLegacyCloud: z.boolean(),
changelogUrl: z.string(),
}); });
export const blockSuiteFeatureFlags = z.object({ 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 AFFINE_STORAGE_KEY = 'affine-local-storage-v2';
export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace'; export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace';
export const UNTITLED_WORKSPACE_NAME = 'Untitled'; export const UNTITLED_WORKSPACE_NAME = 'Untitled';
@@ -76,3 +78,40 @@ export const Messages = {
message: string; 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);
}
}