팬덤 탈퇴 · 성운 창립자 권한 승계 · 대표 팬덤 자동 지정
This commit is contained in:
@@ -329,6 +329,9 @@ abstract interface class PlanetRepository {
|
||||
/// 이 행성/성운에 가입 — `fn-fandom-join`. 이미 멤버면 서버가 아무것도 하지 않는다.
|
||||
Future<void> join();
|
||||
|
||||
/// 탈퇴 — `fn-fandom-leave`. 대표 팬덤 자동 지정(C-101) · 성운 창립자 승계(C-100)는 서버가 한다.
|
||||
Future<void> leave();
|
||||
|
||||
/// 명세 — *최초 5개, 스크롤 시 5개씩 호출*.
|
||||
Future<List<LoungePost>> morePosts({required int offset, int limit = 5});
|
||||
|
||||
@@ -391,6 +394,9 @@ class SamplePlanetRepository implements PlanetRepository {
|
||||
@override
|
||||
Future<void> join() async {}
|
||||
|
||||
@override
|
||||
Future<void> leave() async {}
|
||||
|
||||
@override
|
||||
Future<PlanetHistoryPage> history({String? cursor, bool personal = false}) async => const PlanetHistoryPage(items: []);
|
||||
@override
|
||||
|
||||
@@ -6,6 +6,7 @@ import '../../core/data/backend.dart' show BackendException;
|
||||
import '../../core/data/planet_visual_state.dart';
|
||||
|
||||
import '../../core/theme/tokens.dart';
|
||||
import '../../core/ui/app_dialog.dart';
|
||||
import '../../core/ui/app_icons.dart';
|
||||
import '../eclipse/eclipse_data.dart';
|
||||
import '../eclipse/widgets/eclipse_banner.dart';
|
||||
@@ -74,6 +75,30 @@ class _PlanetDetailScreenState extends State<PlanetDetailScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 「가입중」 알약 → 탈퇴 시트 → 확인 창 — Figma `343:213428`(탈퇴하기 · 취소) ·
|
||||
/// `343:213582`(행성 탈퇴를 할까요?). 대표 팬덤 자동 지정 · 성운 창립자 승계는 서버 몫이다(C-100 · C-101).
|
||||
void _leave() => showActionSheet(context, [
|
||||
ActionSheetItem(context.l10n.planetLeave, () async {
|
||||
final ok = await showConfirmDialog(
|
||||
context,
|
||||
context.l10n.planetLeaveConfirmTitle,
|
||||
body: context.l10n.planetLeaveConfirmBody,
|
||||
confirmLabel: context.l10n.commonConfirm,
|
||||
);
|
||||
if (!ok) return;
|
||||
try {
|
||||
await widget.repository.leave();
|
||||
if (mounted) {
|
||||
setState(() { _detail = widget.repository.load(nebula: widget.nebula); });
|
||||
}
|
||||
} on BackendException catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.message)));
|
||||
}
|
||||
}
|
||||
}),
|
||||
]);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => FutureBuilder<PlanetDetail>(
|
||||
future: _detail,
|
||||
@@ -127,7 +152,7 @@ class _PlanetDetailScreenState extends State<PlanetDetailScreen> {
|
||||
ownerName: d.ownerName,
|
||||
ownerPhoto: d.ownerPhoto,
|
||||
joined: d.joined,
|
||||
onJoin: d.joined ? null : _join,
|
||||
onJoin: d.joined ? _leave : _join,
|
||||
onOpenHistory: () => Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => PlanetHistoryScreen(
|
||||
|
||||
@@ -103,6 +103,9 @@ class FirestorePlanetRepository implements PlanetRepository {
|
||||
@override
|
||||
Future<void> join() => _backend.call('fnFandomJoin', {'fandomId': fandomId});
|
||||
|
||||
@override
|
||||
Future<void> leave() => _backend.call('fnFandomLeave', {'fandomId': fandomId});
|
||||
|
||||
@override
|
||||
Future<PlanetDetail> load({required bool nebula}) async {
|
||||
final db = _backend.db;
|
||||
|
||||
@@ -43,7 +43,7 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
final bool joined;
|
||||
final VoidCallback? onHeroParticipate;
|
||||
|
||||
/// 「가입하기」 알약을 눌렀을 때. 이미 가입했으면 null 이고 알약은 상태만 보인다.
|
||||
/// 알약을 눌렀을 때 — 「가입하기」면 가입, 「가입중」이면 탈퇴 시트. null 이면 상태만 보인다.
|
||||
final VoidCallback? onJoin;
|
||||
|
||||
/// 성운 상세(`373:442708`)는 규모 칩과 FPI 줄이 없다.
|
||||
|
||||
Reference in New Issue
Block a user