Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: configurable changelog url #2418

Merged
merged 7 commits into from May 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/electron/layers/main/src/application-menu.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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 () => {
Expand Down
3 changes: 3 additions & 0 deletions apps/web/preset.config.mjs
Expand Up @@ -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',
};
45 changes: 6 additions & 39 deletions apps/web/src/components/affine/affine-error-eoundary.tsx
@@ -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
Expand Down
@@ -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 {
Expand All @@ -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';
Expand Down
Expand Up @@ -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,
Expand All @@ -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';
Expand Down
@@ -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,
Expand All @@ -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';

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/page-detail-editor.tsx
@@ -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';
Expand All @@ -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';

Expand Down
7 changes: 2 additions & 5 deletions apps/web/src/components/pure/help-island/index.tsx
@@ -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';
Expand Down Expand Up @@ -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 />
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/public-workspace/[workspaceId].tsx
@@ -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';
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/workspace/[workspaceId]/[pageId].tsx
@@ -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';
Expand All @@ -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';
Expand Down
5 changes: 1 addition & 4 deletions apps/web/src/pages/workspace/[workspaceId]/all.tsx
@@ -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';
Expand All @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/pages/workspace/[workspaceId]/setting.tsx
@@ -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';
Expand All @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/plugins/affine/fetcher.ts
@@ -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';
Expand All @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/plugins/affine/index.tsx
@@ -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,
Expand Down Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/plugins/local/index.tsx
Expand Up @@ -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,
Expand All @@ -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';
Expand Down
Expand Up @@ -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({
Expand Down
@@ -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';
Expand Down Expand Up @@ -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,
Expand All @@ -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();
}
}}
>
Expand Down Expand Up @@ -155,7 +159,7 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
<div
className={styles.closeIcon}
onClick={e => {
onReadOrDismissCurrentChangelog(false);
onDismissCurrentChangelog();
e.stopPropagation();
}}
>
Expand Down
1 change: 1 addition & 0 deletions packages/env/src/config.ts
Expand Up @@ -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({
Expand Down
39 changes: 39 additions & 0 deletions packages/env/src/constant.ts
@@ -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';
Expand Down Expand Up @@ -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);
}
}