Remove loading screen

This commit is contained in:
Fedor Indutny
2026-04-16 11:37:43 -07:00
committed by GitHub
parent 8433e9a33d
commit 5fe6a8212f
22 changed files with 1 additions and 347 deletions
-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M116 64c0 28.719-23.281 52-52 52-9.11 0-17.672-2.342-25.117-6.457a3.3 3.3 0 0 0-2.351-.341L13.4 114.599l5.397-23.13a3.3 3.3 0 0 0-.34-2.352C14.341 81.671 12 73.109 12 64c0-28.719 23.281-52 52-52s52 23.281 52 52"/></svg>

Before

Width:  |  Height:  |  Size: 293 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m22.488 117.818 1.363 5.843-10.411 2.43C6.51 127.707.293 121.489 1.91 114.56l2.429-10.411 5.843 1.363-2.43 10.412c-.606 2.598 1.726 4.93 4.324 4.324z"/></svg>

Before

Width:  |  Height:  |  Size: 232 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m118.708 30.77-5.129 3.115a57.7 57.7 0 0 1 6.778 16.351l5.83-1.423a63.6 63.6 0 0 0-7.479-18.044Z"/></svg>

Before

Width:  |  Height:  |  Size: 179 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m127.26 54.235-5.931.915A58.4 58.4 0 0 1 122 64c0 3.01-.229 5.965-.671 8.85l5.931.916c.487-3.184.74-6.446.74-9.766s-.253-6.581-.74-9.765"/></svg>

Before

Width:  |  Height:  |  Size: 219 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M113.579 94.116a57.7 57.7 0 0 0 6.778-16.352l5.83 1.424a63.6 63.6 0 0 1-7.48 18.043z"/></svg>

Before

Width:  |  Height:  |  Size: 167 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m110.792 98.278 4.841 3.546a64.4 64.4 0 0 1-13.81 13.809l-3.546-4.841a58.3 58.3 0 0 0 12.515-12.514"/></svg>

Before

Width:  |  Height:  |  Size: 182 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m94.115 113.579 3.116 5.129a63.6 63.6 0 0 1-18.044 7.479l-1.423-5.83a57.7 57.7 0 0 0 16.351-6.778"/></svg>

Before

Width:  |  Height:  |  Size: 180 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m72.85 121.329.915 5.931c-3.184.487-6.445.74-9.765.74s-6.582-.253-9.766-.74l.916-5.93c2.884.441 5.84.67 8.85.67a58.4 58.4 0 0 0 8.85-.671"/></svg>

Before

Width:  |  Height:  |  Size: 220 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m50.236 120.358-1.424 5.829a63.5 63.5 0 0 1-13.823-5.125l-6.074 1.418-1.363-5.843 8.208-1.916 1.953.995a57.5 57.5 0 0 0 12.523 4.642"/></svg>

Before

Width:  |  Height:  |  Size: 215 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M11.363 100.448 5.52 99.085l1.418-6.074a63.6 63.6 0 0 1-5.125-13.824l5.829-1.423a57.6 57.6 0 0 0 4.642 12.523l.994 1.953z"/></svg>

Before

Width:  |  Height:  |  Size: 204 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m6.67 72.85-5.93.915A64.5 64.5 0 0 1 0 64c0-3.32.253-6.582.74-9.766l5.931.916A58.5 58.5 0 0 0 6 64c0 3.01.229 5.966.67 8.85"/></svg>

Before

Width:  |  Height:  |  Size: 206 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m7.643 50.236-5.83-1.424a63.6 63.6 0 0 1 7.48-18.043l5.129 3.115a57.7 57.7 0 0 0-6.779 16.352"/></svg>

Before

Width:  |  Height:  |  Size: 176 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m17.208 29.723-4.84-3.546a64.4 64.4 0 0 1 13.809-13.81l3.546 4.84a58.3 58.3 0 0 0-12.515 12.515Z"/></svg>

Before

Width:  |  Height:  |  Size: 179 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m33.885 14.421-3.116-5.129a63.6 63.6 0 0 1 18.044-7.48l1.423 5.83a57.7 57.7 0 0 0-16.351 6.78Z"/></svg>

Before

Width:  |  Height:  |  Size: 177 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M64 0c3.32 0 6.582.253 9.766.74l-.916 5.931A58.5 58.5 0 0 0 64 6c-3.009 0-5.964.23-8.85.67L54.235.74A64.5 64.5 0 0 1 64 0"/></svg>

Before

Width:  |  Height:  |  Size: 204 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m79.188 1.813-1.424 5.83a57.7 57.7 0 0 1 16.352 6.779l3.115-5.13a63.6 63.6 0 0 0-18.043-7.479"/></svg>

Before

Width:  |  Height:  |  Size: 176 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="m101.823 12.367-3.545 4.84a58.3 58.3 0 0 1 12.514 12.516l4.841-3.546a64.4 64.4 0 0 0-13.81-13.81"/></svg>

Before

Width:  |  Height:  |  Size: 179 B

-61
View File
@@ -42,67 +42,6 @@
margin: 0;
}
.Inbox__logo {
flex-shrink: 0;
display: block;
width: 128px;
height: 128px;
margin-block: 24px;
position: relative;
@include mixins.light-theme() {
--Inbox__logo__bg: #{variables.$color-ultramarine-logo};
}
@include mixins.dark-theme() {
--Inbox__logo__bg: #{variables.$color-white};
}
.Inbox__logo__part {
width: 100%;
height: 100%;
position: absolute;
}
.Inbox__logo__part--base {
@include mixins.color-svg(
'../images/logo-parts/base.svg',
var(--Inbox__logo__bg)
);
& {
z-index: 1;
}
}
.Inbox__logo__part--segment {
opacity: 0;
z-index: 2;
}
.Inbox__logo__part--animated {
transition:
opacity 250ms,
transform 250ms;
}
@for $i from 1 through 16 {
.Inbox__logo__part--segment:nth-child(#{$i + 1}) {
@include mixins.color-svg(
'../images/logo-parts/p#{$i}.svg',
var(--Inbox__logo__bg)
);
& {
transform: rotate(#{(16 - $i) * 22.5}deg);
}
}
}
.Inbox__logo__part--segment:nth-child(n).Inbox__logo__part--visible {
transform: rotate(0deg);
opacity: 1;
}
}
.Inbox__welcome {
margin-block: 20px 6px;
-74
View File
@@ -1,74 +0,0 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState, useEffect, useMemo } from 'react';
import type { Meta, StoryFn } from '@storybook/react';
import lodash from 'lodash';
import { Inbox } from './Inbox.dom.tsx';
import type { PropsType } from './Inbox.dom.tsx';
import { DAY, SECOND } from '../util/durations/index.std.ts';
const { noop } = lodash;
const { i18n } = window.SignalContext;
export default {
title: 'Components/Inbox',
args: {
i18n,
hasInitialLoadCompleted: false,
isNightly: false,
isCustomizingPreferredReactions: false,
},
argTypes: {
daysAgo: { control: { type: 'number' } },
isNightly: { control: { type: 'boolean' } },
},
} satisfies Meta<PropsType & { daysAgo?: number }>;
const Template: StoryFn<PropsType & { daysAgo?: number }> = ({
daysAgo,
...args
}) => {
const now = useMemo(() => Date.now(), []);
const [dayOffset, setDayOffset] = useState(0);
useEffect(() => {
if (!daysAgo) {
setDayOffset(0);
return noop;
}
const interval = setInterval(() => {
// Increment day offset by 1 / 24 of a day (an hour), and wrap it when it
// reaches `daysAgo` value.
setDayOffset(prevValue => (prevValue + 1 / 24) % daysAgo);
}, SECOND / 10);
return () => clearInterval(interval);
}, [now, daysAgo]);
const firstEnvelopeTimestamp =
daysAgo === undefined ? undefined : now - daysAgo * DAY;
const envelopeTimestamp =
firstEnvelopeTimestamp === undefined
? undefined
: firstEnvelopeTimestamp + dayOffset * DAY;
return (
<Inbox
{...args}
firstEnvelopeTimestamp={firstEnvelopeTimestamp}
envelopeTimestamp={envelopeTimestamp}
renderCustomizingPreferredReactionsModal={() => <div />}
/>
);
};
export const Default = Template.bind({});
export const FourDaysAgo = Template.bind({});
FourDaysAgo.args = {
daysAgo: 4,
};
+1 -162
View File
@@ -2,22 +2,11 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { ReactNode } from 'react';
import React, { useEffect, useState, useMemo } from 'react';
import classNames from 'classnames';
import type { LocalizerType } from '../types/Util.std.ts';
import { createLogger } from '../logging/log.std.ts';
import { SECOND, DAY } from '../util/durations/index.std.ts';
import React from 'react';
import type { SmartNavTabsProps } from '../state/smart/NavTabs.preload.tsx';
import { TitlebarDragArea } from './TitlebarDragArea.dom.tsx';
const log = createLogger('Inbox');
export type PropsType = {
firstEnvelopeTimestamp: number | undefined;
envelopeTimestamp: number | undefined;
hasInitialLoadCompleted: boolean;
i18n: LocalizerType;
isNightly: boolean;
isCustomizingPreferredReactions: boolean;
navTabsCollapsed: boolean;
onToggleNavTabsCollapse: (navTabsCollapsed: boolean) => unknown;
@@ -29,14 +18,7 @@ export type PropsType = {
renderSettingsTab: () => React.JSX.Element;
};
const PART_COUNT = 16;
export function Inbox({
firstEnvelopeTimestamp,
envelopeTimestamp,
hasInitialLoadCompleted,
i18n,
isNightly,
isCustomizingPreferredReactions,
navTabsCollapsed,
onToggleNavTabsCollapse,
@@ -47,149 +29,6 @@ export function Inbox({
renderStoriesTab,
renderSettingsTab,
}: PropsType): React.JSX.Element {
const [internalHasInitialLoadCompleted, setInternalHasInitialLoadCompleted] =
useState(hasInitialLoadCompleted);
const now = useMemo(() => Date.now(), []);
const midnight = useMemo(() => {
const date = new Date(now);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date.getTime();
}, [now]);
useEffect(() => {
if (internalHasInitialLoadCompleted) {
return;
}
const interval = setInterval(() => {
const { status } = window.getSocketStatus().authenticated;
switch (status) {
case 'CONNECTING':
break;
case 'OPEN':
// if we've connected, we can wait for real empty event
clearInterval(interval);
break;
case 'CLOSING':
case 'CLOSED':
clearInterval(interval);
// if we failed to connect, we pretend we loaded
setInternalHasInitialLoadCompleted(true);
break;
default:
log.warn(
`startConnectionListener: Found unexpected socket status ${status}; setting load to done manually.`
);
setInternalHasInitialLoadCompleted(true);
break;
}
}, SECOND);
return () => {
clearInterval(interval);
};
}, [internalHasInitialLoadCompleted]);
useEffect(() => {
setInternalHasInitialLoadCompleted(hasInitialLoadCompleted);
}, [hasInitialLoadCompleted]);
if (!internalHasInitialLoadCompleted) {
let loadingProgress = 100;
if (
firstEnvelopeTimestamp !== undefined &&
envelopeTimestamp !== undefined
) {
loadingProgress =
Math.max(
0,
Math.min(
1,
Math.max(0, envelopeTimestamp - firstEnvelopeTimestamp) /
Math.max(1e-23, now - firstEnvelopeTimestamp)
)
) * 100;
}
let message: string | undefined;
if (envelopeTimestamp !== undefined) {
const daysBeforeMidnight = Math.ceil(
(midnight - envelopeTimestamp) / DAY
);
if (daysBeforeMidnight <= 0) {
message = i18n('icu:loadingMessages--today');
} else if (daysBeforeMidnight === 1) {
message = i18n('icu:loadingMessages--yesterday');
} else {
message = i18n('icu:loadingMessages--other', {
daysAgo: daysBeforeMidnight,
});
}
}
let logo: React.JSX.Element;
if (isNightly) {
const parts = new Array<React.JSX.Element>();
parts.push(
<i key="base" className="Inbox__logo__part Inbox__logo__part--base" />
);
for (let i = 0; i < PART_COUNT; i += 1) {
const isVisible = i <= (loadingProgress * PART_COUNT) / 100;
parts.push(
<i
key={i}
className={classNames({
Inbox__logo__part: true,
'Inbox__logo__part--animated':
firstEnvelopeTimestamp !== undefined && loadingProgress !== 0,
'Inbox__logo__part--segment': true,
'Inbox__logo__part--visible': isVisible,
})}
/>
);
}
logo = <div className="Inbox__logo">{parts}</div>;
} else {
logo = (
<div className="module-splash-screen__logo module-splash-screen__logo--128" />
);
}
return (
<div className="app-loading-screen">
<TitlebarDragArea />
{logo}
{envelopeTimestamp === undefined ? (
<div className="dot-container">
<span className="dot" />
<span className="dot" />
<span className="dot" />
</div>
) : (
<div className="app-loading-screen__progress--container">
<div
className="app-loading-screen__progress--bar"
style={{ transform: `translateX(${loadingProgress - 100}%)` }}
/>
</div>
)}
{message === undefined ? (
<div className="message-placeholder" />
) : (
<div className="message">{message}</div>
)}
<div id="toast" />
</div>
);
}
let activeModal: ReactNode;
if (isCustomizingPreferredReactions) {
activeModal = renderCustomizingPreferredReactionsModal();
-17
View File
@@ -1,17 +0,0 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { createSelector } from 'reselect';
import type { StateType } from '../reducer.preload.ts';
const getInboxState = (state: StateType) => state.inbox;
export const getInboxEnvelopeTimestamp = createSelector(
getInboxState,
({ envelopeTimestamp }) => envelopeTimestamp
);
export const getInboxFirstEnvelopeTimestamp = createSelector(
getInboxState,
({ firstEnvelopeTimestamp }) => firstEnvelopeTimestamp
);
-16
View File
@@ -4,8 +4,6 @@
import React, { memo } from 'react';
import { useSelector } from 'react-redux';
import { Inbox } from '../../components/Inbox.dom.tsx';
import { isNightly } from '../../util/version.std.ts';
import { getIntl } from '../selectors/user.std.ts';
import { SmartCustomizingPreferredReactionsModal } from './CustomizingPreferredReactionsModal.preload.tsx';
import { getIsCustomizingPreferredReactions } from '../selectors/preferredReactions.std.ts';
import type { SmartNavTabsProps } from './NavTabs.preload.tsx';
@@ -15,11 +13,6 @@ import { SmartCallsTab } from './CallsTab.preload.tsx';
import { useItemsActions } from '../ducks/items.preload.ts';
import { getNavTabsCollapsed } from '../selectors/items.dom.ts';
import { SmartChatsTab } from './ChatsTab.preload.tsx';
import { getHasInitialLoadCompleted } from '../selectors/app.std.ts';
import {
getInboxEnvelopeTimestamp,
getInboxFirstEnvelopeTimestamp,
} from '../selectors/inbox.std.ts';
import { SmartPreferences } from './Preferences.preload.tsx';
function renderChatsTab() {
@@ -47,24 +40,15 @@ function renderSettingsTab() {
}
export const SmartInbox = memo(function SmartInbox(): React.JSX.Element {
const i18n = useSelector(getIntl);
const isCustomizingPreferredReactions = useSelector(
getIsCustomizingPreferredReactions
);
const envelopeTimestamp = useSelector(getInboxEnvelopeTimestamp);
const firstEnvelopeTimestamp = useSelector(getInboxFirstEnvelopeTimestamp);
const hasInitialLoadCompleted = useSelector(getHasInitialLoadCompleted);
const navTabsCollapsed = useSelector(getNavTabsCollapsed);
const { toggleNavTabsCollapse } = useItemsActions();
return (
<Inbox
envelopeTimestamp={envelopeTimestamp}
firstEnvelopeTimestamp={firstEnvelopeTimestamp}
hasInitialLoadCompleted={hasInitialLoadCompleted}
i18n={i18n}
isNightly={isNightly(window.getVersion())}
isCustomizingPreferredReactions={isCustomizingPreferredReactions}
navTabsCollapsed={navTabsCollapsed}
onToggleNavTabsCollapse={toggleNavTabsCollapse}