feat(desktop): add offline cache and verified app updates
ci / module boundaries / boundaries (push) Successful in 7s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m2s
ci / ts / ts (packages + web) (push) Successful in 3m8s
ci / desktop / rust (desktop proxy) (push) Successful in 4m21s
release / release (версия и заметки) (push) Successful in 6s
release / android (APK в релиз) (push) Successful in 4m0s
release / desktop (Linux и Windows в релиз) (push) Successful in 11m49s
release / prune (старые файлы и прогоны) (push) Successful in 5s

Clean release notes in Android and desktop update dialogs. Persist downloaded audio and offline playback events per server and user; add desktop update checks, checksum verification and installer launch.
This commit is contained in:
mrleo1nid committed 2026-10-22 22:37:35 +03:00
1 parent 75ae2092ad
commit ab49e22357
27 files changed
+785 -39

No files matched your search

+5
View File
@@ -37,6 +37,7 @@ import { Ambient } from './Ambient';
import { PlayerBar } from './PlayerBar';
import { SearchBox } from './SearchBox';
import s from './AppShell.module.css';
import { DesktopUpdateDialog, DesktopOfflineBanner } from '../features/desktop/DesktopFeatures';
type NavPath =
| '/'
@@ -49,6 +50,7 @@ type NavPath =
| '/uploads/mine'
| '/admin/settings'
| '/collection/playlists'
| '/collection/downloads'
| '/collection/history'
| '/collection/likes'
| '/collection/dislikes';
@@ -147,6 +149,7 @@ function NavSection({
export function AppShell() {
return useAuthState().status === 'signed_in' ? (
<PlayerProvider>
<DesktopUpdateDialog />
<Shell />
</PlayerProvider>
) : null;
@@ -174,6 +177,7 @@ function Shell() {
<NavLink to="/" label={t('nav.home')} icon={homeIcon} activeIcon={homeFillIcon} />
<NavSection mobile={mobile} id="collection" title={t('nav.collection')}>
<NavLink to="/collection/playlists" label={t('playlists.title')} icon={queueIcon} activeIcon={queueIcon} />
{desktop && <NavLink to="/collection/downloads" label={t('desktop.offline')} icon={downloadIcon} activeIcon={downloadIcon} />}
<NavLink to="/collection/history" label={t('nav.history')} icon={historyIcon} activeIcon={historyFillIcon} />
<NavLink to="/collection/likes" label={t('nav.likes')} icon={likeIcon} activeIcon={likeFillIcon} count={counts.likes} />
<NavLink
@@ -298,6 +302,7 @@ function ShellMain() {
const key = useRouterState({ select: (st) => st.location.pathname });
return (
<main id="content" className={s.content} tabIndex={-1}>
<DesktopOfflineBanner />
<div key={key} className={s.routeIn}>
<Suspense fallback={<PageSkeleton />}>
<Outlet />