generated from ttipo/project-base
feat(flutter): 함께 관리 화면을 보는 동안 내 초대 코드를 새로 읽기
일정 연동 코드는 한 번 쓰이면 서버가 바꾸므로, 함께 관리 화면을 열어 둔 동안 15초마다(들어올 때 한 번) 다시 읽어 보여 주는 코드·QR 이 낡지 않게 한다. 안내에 "초대 코드는 한 번 쓰면 새 코드로 바뀌어요."를 더한다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,9 @@ const double _kInviteQr = 130;
|
||||
const double _kInviteRowHeight = _kInviteQr + 11 * 2 + 2;
|
||||
const double _kSheetQr = 196;
|
||||
|
||||
/// 이 화면을 보는 동안 연동 상태를 다시 읽는 간격 — 내 코드로 누가 연동하면 코드가 바뀌고 사람이 늘어난다
|
||||
const Duration _kPageRefresh = Duration(seconds: 15);
|
||||
|
||||
/// 펼쳐지는 영역 (시안 max-height .45s cubic-bezier(.4,0,.2,1))
|
||||
const Duration _kExpand = Duration(milliseconds: 450);
|
||||
|
||||
@@ -68,37 +71,39 @@ class ShareCalendarPage extends ConsumerWidget {
|
||||
final linked = sharing?.linked ?? false;
|
||||
final on = linked || ref.watch(calendarSharingOnProvider);
|
||||
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
AppSpacing.xl,
|
||||
AppSpacing.xs,
|
||||
AppSpacing.xl,
|
||||
MediaQuery.paddingOf(context).bottom + AppSpacing.lg,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SubPageHeader(
|
||||
title: '함께 관리',
|
||||
subtitle: '가족·친구와 같은 달력을 함께 써요',
|
||||
onBack: () => context.pop(),
|
||||
),
|
||||
_ToggleCard(
|
||||
on: on,
|
||||
onChanged: sharing == null ? null : (v) => unawaited(_toggle(context, ref, sharing, v)),
|
||||
),
|
||||
if (!on) const _OffHint(),
|
||||
// 켜면 펼쳐진다
|
||||
AnimatedSize(
|
||||
duration: _kExpand,
|
||||
curve: const Cubic(.4, 0, .2, 1),
|
||||
alignment: Alignment.topCenter,
|
||||
child: on && sharing != null ? _OnBody(sharing: sharing) : const SizedBox(width: double.infinity),
|
||||
),
|
||||
],
|
||||
return _WhileOpenRefresh(
|
||||
child: Scaffold(
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
AppSpacing.xl,
|
||||
AppSpacing.xs,
|
||||
AppSpacing.xl,
|
||||
MediaQuery.paddingOf(context).bottom + AppSpacing.lg,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SubPageHeader(
|
||||
title: '함께 관리',
|
||||
subtitle: '가족·친구와 같은 달력을 함께 써요',
|
||||
onBack: () => context.pop(),
|
||||
),
|
||||
_ToggleCard(
|
||||
on: on,
|
||||
onChanged: sharing == null ? null : (v) => unawaited(_toggle(context, ref, sharing, v)),
|
||||
),
|
||||
if (!on) const _OffHint(),
|
||||
// 켜면 펼쳐진다
|
||||
AnimatedSize(
|
||||
duration: _kExpand,
|
||||
curve: const Cubic(.4, 0, .2, 1),
|
||||
alignment: Alignment.topCenter,
|
||||
child: on && sharing != null ? _OnBody(sharing: sharing) : const SizedBox(width: double.infinity),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -106,6 +111,41 @@ class ShareCalendarPage extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 이 화면을 보는 동안 연동 상태를 자주 다시 읽는다 — 초대 코드는 한 번 쓰면 바뀌므로 보여 주는 코드가 낡지 않게
|
||||
class _WhileOpenRefresh extends ConsumerStatefulWidget {
|
||||
const _WhileOpenRefresh({required this.child});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
ConsumerState<_WhileOpenRefresh> createState() => _WhileOpenRefreshState();
|
||||
}
|
||||
|
||||
class _WhileOpenRefreshState extends ConsumerState<_WhileOpenRefresh> {
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_timer = Timer.periodic(_kPageRefresh, (_) {
|
||||
if (mounted) unawaited(succeeded(ref.read(calendarSharingProvider.notifier).refresh(quiet: true)));
|
||||
});
|
||||
// 들어올 때 한 번 — 다른 화면에 있는 동안 바뀌었을 수 있다
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) unawaited(succeeded(ref.read(calendarSharingProvider.notifier).refresh(quiet: true)));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => widget.child;
|
||||
}
|
||||
|
||||
/// 일정 연동 켜기·끄기 카드
|
||||
class _ToggleCard extends StatelessWidget {
|
||||
const _ToggleCard({required this.on, required this.onChanged});
|
||||
@@ -252,6 +292,8 @@ class _OnBody extends ConsumerWidget {
|
||||
const TextSpan(children: [
|
||||
TextSpan(text: '연동을 하게 되면 '),
|
||||
TextSpan(text: '연동된 사람과 모든 일정이 공유됩니다.', style: TextStyle(fontWeight: FontWeight.w700)),
|
||||
// 한 번 연동에 쓴 코드는 서버가 바꾼다 — 받은 사람이 다시 쓰거나 남에게 넘길 수 없다
|
||||
TextSpan(text: ' 초대 코드는 한 번 쓰면 새 코드로 바뀌어요.'),
|
||||
]),
|
||||
style: _ui(context, 12.5, FontWeight.w400, AppColors.ink2, height: 1.55),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user