Welcome band only for newcomers, with Don't show again

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-09 23:13:34 +03:00
1 parent e0db5cc655
commit 75065f90cd
4 files changed
+40 -4

No files matched your search

+10 -1
View File
@@ -641,6 +641,13 @@ class AppShellState extends State<AppShell> with SingleTickerProviderStateMixin
);
}
/// No Jellyfin account, no server joined or hosted yet, band not
/// dismissed: the welcome band explains the three ways in.
bool get _newcomer =>
!AppSettings.instance.welcomeDismissed.value &&
_jellyfin.isEmpty &&
SessionState.instance.recents.value.isEmpty;
Widget _body(bool online, bool alone) {
final coord = SessionState.instance.coordinator;
final tabBody = switch (_tab) {
@@ -651,12 +658,14 @@ class AppShellState extends State<AppShell> with SingleTickerProviderStateMixin
solo: alone,
// Offline, a put-up starts a solo session, which hosts.
isHost: !online || coord.hostFile != null,
banner: online
// Only for newcomers: the strip has Join and Host for everyone else.
banner: online || !_newcomer
? null
: WelcomeBand(
onJoin: () => _connect(ConnectMode.join),
onHost: () => _connect(ConnectMode.host),
onSolo: _watchSolo,
onDismiss: () => setState(AppSettings.instance.dismissWelcome),
),
jellyfinStart: _libraryStart,
onPutUp: _putUp,
+17 -2
View File
@@ -19,7 +19,8 @@ class WelcomeBand extends StatelessWidget {
final VoidCallback onJoin;
final VoidCallback onHost;
final VoidCallback onSolo;
const WelcomeBand({super.key, required this.onJoin, required this.onHost, required this.onSolo});
final VoidCallback? onDismiss;
const WelcomeBand({super.key, required this.onJoin, required this.onHost, required this.onSolo, this.onDismiss});
@override
Widget build(BuildContext context) {
@@ -40,6 +41,19 @@ class WelcomeBand extends StatelessWidget {
Text(appName, style: t.titleLarge?.copyWith(fontWeight: FontWeight.w700, height: 1.1)),
const SizedBox(height: 2),
Text(appTagline, style: TextStyle(color: scheme.onSurfaceVariant)),
if (onDismiss != null)
TextButton(
key: const ValueKey('welcome-dismiss'),
onPressed: onDismiss,
style: TextButton.styleFrom(
padding: EdgeInsets.zero,
minimumSize: const Size(0, 24),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
foregroundColor: scheme.onSurfaceVariant,
textStyle: const TextStyle(fontSize: 12),
),
child: const Text("Don't show again"),
),
],
),
],
@@ -76,7 +90,7 @@ class WelcomeBand extends StatelessWidget {
],
),
);
return Container(
final band = Container(
key: const ValueKey('welcome-band'),
margin: const EdgeInsets.fromLTRB(20, 16, 20, 0),
padding: const EdgeInsets.all(14),
@@ -110,6 +124,7 @@ class WelcomeBand extends StatelessWidget {
);
}),
);
return band;
}
}
+10
View File
@@ -23,6 +23,7 @@ const _keyProgressLine = 'progressLine';
const _keySoundVolume = 'soundVolume';
const _keySoundsOff = 'soundsOff';
const _keySoundPreset = 'soundPreset';
const _keyWelcomeDismissed = 'welcomeDismissed';
const _keySoundPresetFor = 'soundPresetFor';
const _keyUnreadyOnSwap = 'unreadyOnSwap';
const _keyIdleSitsOut = 'idleSitsOut';
@@ -58,6 +59,8 @@ class AppSettings {
/// The sound set (`SoundPreset` name) every sound uses unless
/// [soundPresetFor] picks another one for it.
final soundPreset = signal('cosmic');
/// The offline welcome band's × was pressed: never show it again.
final welcomeDismissed = signal(false);
/// `SfxKind` name -> `SoundPreset` name, per-sound overrides.
final soundPresetFor = signal<Map<String, String>>(const {});
@@ -110,6 +113,8 @@ class AppSettings {
if (vol is num) soundVolume.value = vol.toDouble().clamp(0, 1);
final off = box.get(_keySoundsOff);
if (off is List) soundsOff.value = Set.unmodifiable(off.whereType<String>());
final welcomeOff = box.get(_keyWelcomeDismissed);
if (welcomeOff is bool) welcomeDismissed.value = welcomeOff;
final soundSet = box.get(_keySoundPreset);
if (soundSet is String) soundPreset.value = soundSet;
final per = box.get(_keySoundPresetFor);
@@ -186,6 +191,11 @@ class AppSettings {
_put(_keySoundsOff, soundsOff.value.toList());
}
void dismissWelcome() {
welcomeDismissed.value = true;
_put(_keyWelcomeDismissed, true);
}
void setSoundPreset(String preset) {
soundPreset.value = preset;
_put(_keySoundPreset, preset);
+3 -1
View File
@@ -733,7 +733,9 @@ always scrolls the page). Space never presses a focused button
bytes). Online, a name change (once typing settles) or picture change
goes out through `Profile.push` (`coordinator.updateProfile`).
- **Welcome** (`welcome.dart`): offline the Library opens with
`WelcomeBand` over the source switch (sizes away when online): the app
`WelcomeBand` over the source switch, only for newcomers (no Jellyfin
account, no recent server, not dismissed with "Don't show again";
sizes away when online): the app
icon, Starsync and "Watch together, in sync", then three `WayCard`s,
Join a friend first (filled), Host, Watch solo (opens Files, or
Jellyfin when linked); beside the name from 940 px, under it below,