Fix black sheet/dialog barriers and Details tabs refetching on switch
Every sheet and dialog barrier goes solid black instead of dimming the
screen behind it whenever dynamic color ("Match wallpaper") is on -
Material 3's ColorScheme.scrim role is fully opaque black by spec,
meant to be used at reduced opacity by whoever paints it, but
NooColors.fromDynamicScheme mapped it straight into barrierColor.
Use the fixed palette's already-translucent scrim instead, matching
how success/warning/info already fall back to it since they have no
dynamic equivalent either.
Also fix the Details sheet's Info/Versions/Activity segmented control
refetching a tab's data every time it's selected: switching on the
active tab picked which single widget to build, so Flutter tore down
and recreated whichever tab wasn't showing on every switch, discarding
its fetched data. Keep all three mounted in an IndexedStack instead
(the same pattern the app's own main tab bar already uses for this
exact reason), so each tab's state - and its one-shot fetch - survives
switching back and forth.
This commit is contained in:
@@ -133,7 +133,12 @@ class NooColors extends ThemeExtension<NooColors> {
|
|||||||
/// palettes. `success`/`successSoft`/`warning`/`warningSoft`/`info`/
|
/// palettes. `success`/`successSoft`/`warning`/`warningSoft`/`info`/
|
||||||
/// `infoSoft` have no Material dynamic equivalent and are content-identity
|
/// `infoSoft` have no Material dynamic equivalent and are content-identity
|
||||||
/// colors regardless (file-type tiles) rather than brand colors, so they
|
/// colors regardless (file-type tiles) rather than brand colors, so they
|
||||||
/// always come from the fixed palette matching [cs]'s brightness.
|
/// always come from the fixed palette matching [cs]'s brightness. Same
|
||||||
|
/// for `scrim`: Material 3's `ColorScheme.scrim` role is fully *opaque*
|
||||||
|
/// black (`0xFF000000`), meant to be used at reduced opacity by whoever
|
||||||
|
/// paints it, not painted directly - using it as-is for a sheet/dialog's
|
||||||
|
/// `barrierColor` hid the screen behind completely instead of dimming it,
|
||||||
|
/// so this uses the fixed palette's already-translucent scrim instead.
|
||||||
factory NooColors.fromDynamicScheme(ColorScheme cs) {
|
factory NooColors.fromDynamicScheme(ColorScheme cs) {
|
||||||
final fixed = cs.brightness == Brightness.dark ? dark : light;
|
final fixed = cs.brightness == Brightness.dark ? dark : light;
|
||||||
return NooColors(
|
return NooColors(
|
||||||
@@ -157,7 +162,7 @@ class NooColors extends ThemeExtension<NooColors> {
|
|||||||
warningSoft: fixed.warningSoft,
|
warningSoft: fixed.warningSoft,
|
||||||
info: fixed.info,
|
info: fixed.info,
|
||||||
infoSoft: fixed.infoSoft,
|
infoSoft: fixed.infoSoft,
|
||||||
scrim: cs.scrim,
|
scrim: fixed.scrim,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,12 @@ class DetailsSheet extends StatelessWidget {
|
|||||||
/// [StatefulWidget] rather than three fields on [DetailsSheet] so the
|
/// [StatefulWidget] rather than three fields on [DetailsSheet] so the
|
||||||
/// selection survives independently of how the header/container around it
|
/// selection survives independently of how the header/container around it
|
||||||
/// is built (mobile embeds this once, desktop hands it to [showNooDialog]
|
/// is built (mobile embeds this once, desktop hands it to [showNooDialog]
|
||||||
/// directly).
|
/// directly). All three tabs are built once and kept mounted in an
|
||||||
|
/// [IndexedStack] rather than swapped in/out of the tree - Versions and
|
||||||
|
/// Activity each fetch on their own first build (see their `_requested`
|
||||||
|
/// guard), so switching tabs via a bare `switch` on the selected type would
|
||||||
|
/// tear down and rebuild whichever tab isn't showing, discarding its
|
||||||
|
/// fetched data and re-requesting it every time the user switched back.
|
||||||
class _DetailsBody extends StatefulWidget {
|
class _DetailsBody extends StatefulWidget {
|
||||||
final NextcloudItem item;
|
final NextcloudItem item;
|
||||||
|
|
||||||
@@ -138,11 +143,14 @@ class _DetailsBodyState extends State<_DetailsBody> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: NooSpace.lg),
|
const SizedBox(height: NooSpace.lg),
|
||||||
switch (_tab) {
|
IndexedStack(
|
||||||
_DetailsTab.info => DetailsInfoTab(item: widget.item),
|
index: _tab.index,
|
||||||
_DetailsTab.versions => DetailsVersionsTab(item: widget.item),
|
children: [
|
||||||
_DetailsTab.activity => DetailsActivityTab(item: widget.item),
|
DetailsInfoTab(item: widget.item),
|
||||||
},
|
DetailsVersionsTab(item: widget.item),
|
||||||
|
DetailsActivityTab(item: widget.item),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,22 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('NooColors.fromDynamicScheme', () {
|
||||||
|
test('scrim comes from the fixed palette, not the opaque dynamic role', () {
|
||||||
|
// Material 3's ColorScheme.scrim is fully opaque black - using it
|
||||||
|
// directly as a sheet/dialog barrierColor hid the screen behind
|
||||||
|
// completely instead of dimming it.
|
||||||
|
final dynamicScheme = ColorScheme.fromSeed(
|
||||||
|
seedColor: const Color(0xFF009688),
|
||||||
|
brightness: Brightness.light,
|
||||||
|
);
|
||||||
|
expect(dynamicScheme.scrim.a, 1.0);
|
||||||
|
final nooColors = NooColors.fromDynamicScheme(dynamicScheme);
|
||||||
|
expect(nooColors.scrim, NooColors.light.scrim);
|
||||||
|
expect(nooColors.scrim.a, lessThan(1.0));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('NooAvatar', () {
|
group('NooAvatar', () {
|
||||||
testNooWidgets('current user uses accent-soft/accent-text', (
|
testNooWidgets('current user uses accent-soft/accent-text', (
|
||||||
tester,
|
tester,
|
||||||
|
|||||||
Reference in New Issue
Block a user