mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
fix: left sidebar style fixes (#3950)
Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
@@ -18,21 +18,23 @@ export const root = style({
|
||||
'&:hover': {
|
||||
background: 'var(--affine-white-60)',
|
||||
},
|
||||
'&[data-has-update="true"]:before': {
|
||||
'&[data-disabled="true"]': {
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
'&:after': {
|
||||
content: "''",
|
||||
position: 'absolute',
|
||||
top: '-3px',
|
||||
right: '-3px',
|
||||
top: '-2px',
|
||||
right: '-2px',
|
||||
width: '8px',
|
||||
height: '8px',
|
||||
backgroundColor: 'var(--affine-primary-color)',
|
||||
borderRadius: '50%',
|
||||
zIndex: 1,
|
||||
opacity: 1,
|
||||
transition: '0.3s ease',
|
||||
transition: 'opacity 0.3s',
|
||||
},
|
||||
'&[data-disabled="true"]': {
|
||||
pointerEvents: 'none',
|
||||
'&:hover:after': {
|
||||
opacity: 0,
|
||||
},
|
||||
},
|
||||
vars: {
|
||||
@@ -42,7 +44,7 @@ export const root = style({
|
||||
|
||||
export const icon = style({
|
||||
marginRight: '18px',
|
||||
color: 'var(--affine-primary-color)',
|
||||
color: 'var(--affine-icon-color)',
|
||||
fontSize: '24px',
|
||||
});
|
||||
|
||||
@@ -90,7 +92,7 @@ export const installLabelNormal = style([
|
||||
{
|
||||
justifyContent: 'space-between',
|
||||
selectors: {
|
||||
[`${root}:hover &`]: {
|
||||
[`${root}:hover &, ${root}[data-updating=true] &`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
@@ -102,7 +104,7 @@ export const installLabelHover = style([
|
||||
{
|
||||
display: 'none',
|
||||
selectors: {
|
||||
[`${root}:hover &`]: {
|
||||
[`${root}:hover &, ${root}[data-updating=true] &`]: {
|
||||
display: 'flex',
|
||||
},
|
||||
},
|
||||
@@ -175,7 +177,7 @@ export const particles = style({
|
||||
pointerEvents: 'none',
|
||||
display: 'none',
|
||||
selectors: {
|
||||
[`${root}:hover &`]: {
|
||||
[`${root}:hover &, ${root}[data-updating=true] &`]: {
|
||||
display: 'block',
|
||||
},
|
||||
'&:before': {
|
||||
@@ -224,8 +226,10 @@ export const halo = style({
|
||||
'radial-gradient(ellipse 30% 45% at bottom, rgba(30, 150, 235, 0.6), transparent)',
|
||||
},
|
||||
selectors: {
|
||||
'&:hover:before, &:hover:after': {
|
||||
transform: 'translateY(0) scale(1)',
|
||||
},
|
||||
[`${root}:hover &:before, ${root}:hover &:after,
|
||||
${root}[data-updating=true] &:before, ${root}[data-updating=true] &:after`]:
|
||||
{
|
||||
transform: 'translateY(0) scale(1)',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { isBrowser } from '@affine/env/constant';
|
||||
import type { UpdateMeta } from '@toeverything/infra';
|
||||
import { atomWithObservable, atomWithStorage } from 'jotai/utils';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@@ -8,7 +9,7 @@ function rpcToObservable<
|
||||
H extends () => Promise<T>,
|
||||
E extends (callback: (t: T) => void) => () => void,
|
||||
>(
|
||||
initialValue: T,
|
||||
initialValue: T | null,
|
||||
{
|
||||
event,
|
||||
handler,
|
||||
@@ -18,8 +19,8 @@ function rpcToObservable<
|
||||
handler?: H;
|
||||
onSubscribe?: () => void;
|
||||
}
|
||||
) {
|
||||
return new Observable<T>(subscriber => {
|
||||
): Observable<T | null> {
|
||||
return new Observable<T | null>(subscriber => {
|
||||
subscriber.next(initialValue);
|
||||
onSubscribe?.();
|
||||
if (!isBrowser || !environment.isDesktop || !event) {
|
||||
@@ -40,13 +41,13 @@ function rpcToObservable<
|
||||
}
|
||||
|
||||
export const updateReadyAtom = atomWithObservable(() => {
|
||||
return rpcToObservable(null as any | null, {
|
||||
return rpcToObservable(null as UpdateMeta | null, {
|
||||
event: window.events?.updater.onUpdateReady,
|
||||
});
|
||||
});
|
||||
|
||||
export const updateAvailableAtom = atomWithObservable(() => {
|
||||
return rpcToObservable(null as any | null, {
|
||||
return rpcToObservable(null as UpdateMeta | null, {
|
||||
event: window.events?.updater.onUpdateAvailable,
|
||||
onSubscribe: () => {
|
||||
window.apis?.updater.checkForUpdatesAndNotify().catch(err => {
|
||||
@@ -56,8 +57,8 @@ export const updateAvailableAtom = atomWithObservable(() => {
|
||||
});
|
||||
});
|
||||
|
||||
export const downloadProgressAtom = atomWithObservable<number>(() => {
|
||||
return rpcToObservable(0, {
|
||||
export const downloadProgressAtom = atomWithObservable(() => {
|
||||
return rpcToObservable(null as number | null, {
|
||||
event: window.events?.updater.onDownloadProgress,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,7 +14,17 @@ import {
|
||||
updateReadyAtom,
|
||||
} from './index.jotai';
|
||||
|
||||
interface AddPageButtonProps {
|
||||
export interface AddPageButtonPureProps {
|
||||
onClickUpdate: () => void;
|
||||
onDismissCurrentChangelog: () => void;
|
||||
currentChangelogUnread: boolean;
|
||||
updateReady: boolean;
|
||||
updateAvailable: {
|
||||
version: string;
|
||||
allowAutoUpdate: boolean;
|
||||
} | null;
|
||||
downloadProgress: number | null;
|
||||
appQuitting: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
@@ -39,61 +49,19 @@ const currentChangelogUnreadAtom = atom(async get => {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Although it is called an input, it is actually a button.
|
||||
export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
export function AppUpdaterButtonPure({
|
||||
updateReady,
|
||||
onClickUpdate,
|
||||
onDismissCurrentChangelog,
|
||||
currentChangelogUnread,
|
||||
updateAvailable,
|
||||
downloadProgress,
|
||||
appQuitting,
|
||||
className,
|
||||
style,
|
||||
}: AddPageButtonPureProps) {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const currentChangelogUnread = useAtomValue(currentChangelogUnreadAtom);
|
||||
const updateReady = useAtomValue(updateReadyAtom);
|
||||
const updateAvailable = useAtomValue(updateAvailableAtom);
|
||||
const currentVersion = useAtomValue(currentVersionAtom);
|
||||
const downloadProgress = useAtomValue(downloadProgressAtom);
|
||||
const setChangelogCheckAtom = useSetAtom(changelogCheckedAtom);
|
||||
const [appQuitting, setAppQuitting] = useState(false);
|
||||
|
||||
const onDismissCurrentChangelog = useCallback(() => {
|
||||
if (!currentVersion) {
|
||||
return;
|
||||
}
|
||||
startTransition(() =>
|
||||
setChangelogCheckAtom(mapping => {
|
||||
return {
|
||||
...mapping,
|
||||
[currentVersion]: true,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [currentVersion, setChangelogCheckAtom]);
|
||||
const onClickUpdate = useCallback(() => {
|
||||
if (updateReady) {
|
||||
setAppQuitting(true);
|
||||
window.apis?.updater.quitAndInstall().catch(err => {
|
||||
// TODO: add error toast here
|
||||
console.error(err);
|
||||
});
|
||||
} 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(runtimeConfig.changelogUrl, '_blank');
|
||||
onDismissCurrentChangelog();
|
||||
} else {
|
||||
throw new Unreachable();
|
||||
}
|
||||
}, [
|
||||
currentChangelogUnread,
|
||||
currentVersion,
|
||||
onDismissCurrentChangelog,
|
||||
updateAvailable,
|
||||
updateReady,
|
||||
]);
|
||||
|
||||
if (!updateAvailable && !currentChangelogUnread) {
|
||||
return null;
|
||||
}
|
||||
@@ -125,7 +93,8 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
<button
|
||||
style={style}
|
||||
className={clsx([styles.root, className])}
|
||||
data-has-update={updateAvailable ? 'true' : 'false'}
|
||||
data-has-update={!!updateAvailable}
|
||||
data-updating={appQuitting}
|
||||
data-disabled={
|
||||
(updateAvailable?.allowAutoUpdate && !updateReady) || appQuitting
|
||||
}
|
||||
@@ -157,7 +126,9 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
<div className={clsx([styles.installLabelHover])}>
|
||||
<ResetIcon className={styles.icon} />
|
||||
<span className={styles.ellipsisTextOverflow}>
|
||||
{t['com.affine.updater.restart-to-update']()}
|
||||
{t[
|
||||
appQuitting ? 'Loading' : 'com.affine.updater.restart-to-update'
|
||||
]()}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
@@ -215,3 +186,76 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Although it is called an input, it is actually a button.
|
||||
export function AppUpdaterButton({
|
||||
className,
|
||||
style,
|
||||
}: {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}) {
|
||||
const currentChangelogUnread = useAtomValue(currentChangelogUnreadAtom);
|
||||
const updateReady = useAtomValue(updateReadyAtom);
|
||||
const updateAvailable = useAtomValue(updateAvailableAtom);
|
||||
const currentVersion = useAtomValue(currentVersionAtom);
|
||||
const downloadProgress = useAtomValue(downloadProgressAtom);
|
||||
const setChangelogCheckAtom = useSetAtom(changelogCheckedAtom);
|
||||
const [appQuitting, setAppQuitting] = useState(false);
|
||||
|
||||
const onDismissCurrentChangelog = useCallback(() => {
|
||||
if (!currentVersion) {
|
||||
return;
|
||||
}
|
||||
startTransition(() =>
|
||||
setChangelogCheckAtom(mapping => {
|
||||
return {
|
||||
...mapping,
|
||||
[currentVersion]: true,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [currentVersion, setChangelogCheckAtom]);
|
||||
const onClickUpdate = useCallback(() => {
|
||||
if (updateReady) {
|
||||
setAppQuitting(true);
|
||||
window.apis?.updater.quitAndInstall().catch(err => {
|
||||
// TODO: add error toast here
|
||||
console.error(err);
|
||||
});
|
||||
} 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(runtimeConfig.changelogUrl, '_blank');
|
||||
onDismissCurrentChangelog();
|
||||
} else {
|
||||
throw new Unreachable();
|
||||
}
|
||||
}, [
|
||||
currentChangelogUnread,
|
||||
currentVersion,
|
||||
onDismissCurrentChangelog,
|
||||
updateAvailable,
|
||||
updateReady,
|
||||
]);
|
||||
return (
|
||||
<AppUpdaterButtonPure
|
||||
appQuitting={appQuitting}
|
||||
updateReady={!!updateReady}
|
||||
onClickUpdate={onClickUpdate}
|
||||
onDismissCurrentChangelog={onDismissCurrentChangelog}
|
||||
currentChangelogUnread={currentChangelogUnread}
|
||||
updateAvailable={updateAvailable}
|
||||
downloadProgress={downloadProgress}
|
||||
className={className}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export const mainContainerStyle = style({
|
||||
backgroundColor: 'var(--affine-background-primary-color)',
|
||||
selectors: {
|
||||
'&[data-show-padding="true"]': {
|
||||
margin: '8px',
|
||||
margin: '8px 8px 8px 0',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
boxShadow: 'var(--affine-shadow-1)',
|
||||
|
||||
Reference in New Issue
Block a user