Skip to content

Commit 05a9169

Browse files
shinyfordslightfoot
authored andcommitted
fix: improve ui around signing out of sessions [CLERK_SDK #20]
1 parent 25f74fe commit 05a9169

File tree

3 files changed

+83
-11
lines changed

3 files changed

+83
-11
lines changed

packages/clerk_flutter/lib/src/widgets/ui/closeable.dart

+59-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import 'package:flutter/material.dart';
22

3-
class Closeable extends StatelessWidget {
4-
static const _defaultDuration = Duration(milliseconds: 250);
3+
const _defaultDuration = Duration(milliseconds: 250);
54

5+
/// [Closeable] provides a widget that will animate to closed or open positions depending
6+
/// on the `open` or `closed` parameter values. One and only one of `open` or `closed` must
7+
/// be provided.
8+
class Closeable extends StatelessWidget {
69
final Duration duration;
710
final double _value;
811
final Widget child;
12+
final Axis orientation;
913

1014
const Closeable({
1115
super.key,
1216
bool? closed,
1317
bool? open,
1418
required this.child,
1519
this.duration = _defaultDuration,
20+
this.orientation = Axis.vertical,
1621
}) : assert((closed is bool) || (open is bool), 'One of closed or open required'),
1722
assert((closed is bool) != (open is bool), 'Only one of closed or open allowed'),
1823
_value = (open == true || closed == false) ? 1 : 0;
@@ -25,10 +30,61 @@ class Closeable extends StatelessWidget {
2530
child: AnimatedAlign(
2631
duration: duration,
2732
alignment: Alignment.topLeft,
28-
heightFactor: _value,
33+
heightFactor: orientation == Axis.vertical ? _value : null,
34+
widthFactor: orientation == Axis.horizontal ? _value : null,
2935
child: child,
3036
),
3137
),
3238
);
3339
}
3440
}
41+
42+
/// [AnimatingCloseable] provides a closeable widget just like [Closeable]
43+
/// with the minor difference that it animates to its first position from closed
44+
class AnimatingCloseable extends StatefulWidget {
45+
final Duration duration;
46+
final bool? open;
47+
final bool? closed;
48+
final Widget child;
49+
final Axis orientation;
50+
51+
const AnimatingCloseable({
52+
super.key,
53+
this.open,
54+
this.closed,
55+
required this.child,
56+
this.duration = _defaultDuration,
57+
this.orientation = Axis.vertical,
58+
}) : assert((closed is bool) || (open is bool), 'One of closed or open required'),
59+
assert((closed is bool) != (open is bool), 'Only one of closed or open allowed');
60+
61+
@override
62+
State<AnimatingCloseable> createState() => _AnimatingCloseableState();
63+
}
64+
65+
class _AnimatingCloseableState extends State<AnimatingCloseable> {
66+
bool? open = false;
67+
bool? closed;
68+
69+
@override
70+
void initState() {
71+
super.initState();
72+
WidgetsBinding.instance.addPostFrameCallback((_) {
73+
setState(() {
74+
open = widget.open;
75+
closed = widget.closed;
76+
});
77+
});
78+
}
79+
80+
@override
81+
Widget build(BuildContext context) {
82+
return Closeable(
83+
duration: widget.duration,
84+
open: open,
85+
closed: closed,
86+
orientation: widget.orientation,
87+
child: widget.child,
88+
);
89+
}
90+
}

packages/clerk_flutter/lib/src/widgets/user/clerk_user_button.dart

+5-8
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,12 @@ class _ClerkUserButtonState extends State<ClerkUserButton> {
2626
child: ClerkAuthBuilder(builder: (context, auth) {
2727
final translator = auth.translator;
2828

29-
for (final session in auth.client.sessions) {
30-
final idx = _sessions.indexWhere((s) => s.id == session.id);
31-
if (idx > -1) {
32-
_sessions[idx] = session;
33-
} else {
34-
_sessions.add(session);
35-
}
36-
}
29+
// adding to a list of existing sessions means we have ones that are now deleted
30+
// available for prettier UI
31+
_sessions.addOrReplaceAll(auth.client.sessions, by: (s) => s.id);
3732

33+
// after a delay period, all deleted sessions will have been closed, so we can
34+
// clear the `_sessions` cache of any such for next time round
3835
Future.delayed(_closeDelay, () => _sessions = [...auth.client.sessions]);
3936

4037
return ClerkVerticalCard(

packages/common/lib/src/extensions.dart

+19
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,22 @@ extension StringExtension on String {
3030
.map((t) => t[0])
3131
.join();
3232
}
33+
34+
extension ListExtension on List {
35+
void addOrReplaceAll<T>(Iterable<T> list, {dynamic Function(T)? by}) {
36+
if (isEmpty) {
37+
addAll(list);
38+
} else {
39+
by ??= (t) => t;
40+
for (final item in list) {
41+
final identifier = by.call(item);
42+
final idx = indexWhere((i) => by!.call(i) == identifier);
43+
if (idx > -1) {
44+
this[idx] = item;
45+
} else {
46+
add(item);
47+
}
48+
}
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)