mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
feat(player-stats): local listening history tab with heatmap and summaries (#849)
* feat(player-stats): local listening history tab with heatmap and summaries Record play sessions in library.sqlite when the library index is enabled, add Rust read APIs and Tauri commands for year/day aggregates, and ship the Player stats UI with session clustering, event-driven live refresh, and a notice when some servers are excluded from indexing. * test(player-stats): split play_session repo and expand test coverage Move the repository into play_session/ (completion, cluster, integration tests), add remap/purge/FK coverage in Rust, and cover ingestion gates plus live-refresh hooks on the frontend per spec v0.3. * docs(release): CHANGELOG and credits for player stats (PR #849) * fix(player-stats): satisfy tsc and clippy CI gates Use InternetRadioStation field names in the radio skip test and replace manual month/day range checks with RangeInclusive::contains.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { Info } from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../../store/authStore';
|
||||
import { useLibraryIndexStore } from '../../store/libraryIndexStore';
|
||||
|
||||
export default function PlayerStatsPartialIndexNotice() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const servers = useAuthStore(s => s.servers);
|
||||
const masterEnabled = useLibraryIndexStore(s => s.masterEnabled);
|
||||
const syncExcludedByServer = useLibraryIndexStore(s => s.syncExcludedByServer);
|
||||
|
||||
const excludedCount = useMemo(
|
||||
() => servers.filter(s => syncExcludedByServer[s.id] === true).length,
|
||||
[servers, syncExcludedByServer],
|
||||
);
|
||||
|
||||
if (!masterEnabled || excludedCount === 0 || servers.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="settings-hint settings-hint-info player-stats-partial-index-notice" role="status">
|
||||
<Info size={16} aria-hidden style={{ flexShrink: 0, marginTop: 2 }} />
|
||||
<span>
|
||||
{t('statistics.playerPartialIndexNotice')}
|
||||
{' '}
|
||||
<button
|
||||
type="button"
|
||||
className="player-stats-partial-index-link"
|
||||
onClick={() => navigate('/settings', { state: { tab: 'library' } })}
|
||||
>
|
||||
{t('statistics.playerPartialIndexSettings')}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user