🐛 Bug fixes
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/poll.dart';
|
import 'package:island/models/poll.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
|
||||||
@@ -57,11 +59,9 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
|||||||
final String pubName;
|
final String pubName;
|
||||||
|
|
||||||
Future<void> _createPoll(BuildContext context) async {
|
Future<void> _createPoll(BuildContext context) async {
|
||||||
// Use named route defined in router with :name param (creatorPollNew)
|
|
||||||
final result = await GoRouter.of(
|
final result = await GoRouter.of(
|
||||||
context,
|
context,
|
||||||
).pushNamed('creatorPollNew', pathParameters: {'name': pubName});
|
).pushNamed('creatorPollNew', pathParameters: {'name': pubName});
|
||||||
// If PollEditorScreen returns a created SnPoll on success, pop back with it
|
|
||||||
if (result is SnPoll && context.mounted) {
|
if (result is SnPoll && context.mounted) {
|
||||||
Navigator.of(context).maybePop(result);
|
Navigator.of(context).maybePop(result);
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
|||||||
return endItemView;
|
return endItemView;
|
||||||
}
|
}
|
||||||
final poll = data.items[index];
|
final poll = data.items[index];
|
||||||
return _CreatorPollItem(poll: poll);
|
return _CreatorPollItem(poll: poll, pubName: pubName);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -103,7 +103,8 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CreatorPollItem extends StatelessWidget {
|
class _CreatorPollItem extends StatelessWidget {
|
||||||
const _CreatorPollItem({required this.poll});
|
final String pubName;
|
||||||
|
const _CreatorPollItem({required this.poll, required this.pubName});
|
||||||
|
|
||||||
final SnPoll poll;
|
final SnPoll poll;
|
||||||
|
|
||||||
@@ -143,24 +144,23 @@ class _CreatorPollItem extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing: PopupMenuButton<String>(
|
trailing: PopupMenuButton<String>(
|
||||||
onSelected: (v) {
|
|
||||||
switch (v) {
|
|
||||||
case 'edit':
|
|
||||||
// Use global router helper if desired
|
|
||||||
// context.push('/creators/${poll.publisher?.name ?? ''}/polls/${poll.id}/edit');
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
'creatorPollEdit',
|
|
||||||
arguments: {
|
|
||||||
'name': poll.publisher?.name ?? '',
|
|
||||||
'id': poll.id,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context) => [
|
(context) => [
|
||||||
const PopupMenuItem(value: 'edit', child: Text('Edit')),
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.edit),
|
||||||
|
const Gap(16),
|
||||||
|
Text('Edit'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'creatorPollEdit',
|
||||||
|
pathParameters: {'name': pubName, 'id': poll.id},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -6,7 +8,6 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/post/publishers_modal.dart';
|
|
||||||
import 'package:island/models/poll.dart';
|
import 'package:island/models/poll.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
@@ -63,14 +64,38 @@ class PollEditor extends Notifier<PollEditorState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEditingId(String? id) {
|
Future<void> setEditingId(BuildContext context, String? id) async {
|
||||||
state = PollEditorState(
|
if (id == null || id.isEmpty) return;
|
||||||
id: id,
|
|
||||||
title: state.title,
|
showLoadingModal(context);
|
||||||
description: state.description,
|
final dio = ref.read(apiClientProvider);
|
||||||
endedAt: state.endedAt,
|
try {
|
||||||
questions: [...state.questions],
|
final res = await dio.get('/sphere/polls/$id');
|
||||||
);
|
|
||||||
|
// Handle both plain object and wrapped response formats.
|
||||||
|
final dynamic payload = res.data;
|
||||||
|
final Map<String, dynamic> json =
|
||||||
|
payload is Map && payload['data'] is Map<String, dynamic>
|
||||||
|
? Map<String, dynamic>.from(payload['data'] as Map)
|
||||||
|
: Map<String, dynamic>.from(payload as Map);
|
||||||
|
|
||||||
|
final poll = SnPoll.fromJson(json);
|
||||||
|
|
||||||
|
state = PollEditorState(
|
||||||
|
id: poll.id,
|
||||||
|
title: poll.title,
|
||||||
|
description: poll.description,
|
||||||
|
endedAt: poll.endedAt,
|
||||||
|
questions: poll.questions,
|
||||||
|
);
|
||||||
|
} on DioException catch (e) {
|
||||||
|
log('Failed to load poll $id: ${e.message}');
|
||||||
|
// Keep state with id set; UI may handle error display.
|
||||||
|
} catch (e) {
|
||||||
|
log('Unexpected error loading poll $id: $e');
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addQuestion(SnPollQuestionType type) {
|
void addQuestion(SnPollQuestionType type) {
|
||||||
@@ -313,32 +338,10 @@ class PollEditorScreen extends ConsumerWidget {
|
|||||||
|
|
||||||
// Submit helpers declared before build to avoid forward reference issues
|
// Submit helpers declared before build to avoid forward reference issues
|
||||||
|
|
||||||
static Future<void> _submitPoll(BuildContext context, WidgetRef ref) async {
|
Future<void> _submitPoll(BuildContext context, WidgetRef ref) async {
|
||||||
final model = ref.watch(pollEditorProvider);
|
final model = ref.watch(pollEditorProvider);
|
||||||
final dio = ref.read(apiClientProvider);
|
final dio = ref.read(apiClientProvider);
|
||||||
|
|
||||||
// Pick publisher (required)
|
|
||||||
final pickedPublisher = await showModalBottomSheet<dynamic>(
|
|
||||||
context: context,
|
|
||||||
useRootNavigator: true,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (_) => const PublisherModal(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pickedPublisher == null) {
|
|
||||||
showSnackBar('Publisher is required');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String publisherName =
|
|
||||||
pickedPublisher.name ?? pickedPublisher['name'] ?? '';
|
|
||||||
if (publisherName.isEmpty) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Invalid publisher selected')),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build payload
|
// Build payload
|
||||||
final body = {
|
final body = {
|
||||||
'title': model.title,
|
'title': model.title,
|
||||||
@@ -376,33 +379,21 @@ class PollEditorScreen extends ConsumerWidget {
|
|||||||
await (isUpdate
|
await (isUpdate
|
||||||
? dio.patch(
|
? dio.patch(
|
||||||
path,
|
path,
|
||||||
queryParameters: {'pub': publisherName},
|
queryParameters: {'pub': initialPublisher},
|
||||||
data: body,
|
data: body,
|
||||||
)
|
)
|
||||||
: dio.post(
|
: dio.post(
|
||||||
path,
|
path,
|
||||||
queryParameters: {'pub': publisherName},
|
queryParameters: {'pub': initialPublisher},
|
||||||
data: body,
|
data: body,
|
||||||
));
|
));
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showSnackBar(isUpdate ? 'Poll updated.' : 'Poll created.');
|
||||||
SnackBar(content: Text(isUpdate ? 'Poll updated.' : 'Poll created.')),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
Navigator.of(context).maybePop(res.data);
|
Navigator.of(context).maybePop(res.data);
|
||||||
} on DioException catch (e) {
|
|
||||||
final msg =
|
|
||||||
e.response?.data is Map && (e.response!.data['message'] != null)
|
|
||||||
? e.response!.data['message'].toString()
|
|
||||||
: e.message ?? 'Network error';
|
|
||||||
ScaffoldMessenger.of(
|
|
||||||
context,
|
|
||||||
).showSnackBar(SnackBar(content: Text('Failed: $msg')));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ScaffoldMessenger.of(
|
showErrorAlert(e);
|
||||||
context,
|
|
||||||
).showSnackBar(SnackBar(content: Text('Unexpected error: $e')));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +408,9 @@ class PollEditorScreen extends ConsumerWidget {
|
|||||||
|
|
||||||
// initialize editing state if provided
|
// initialize editing state if provided
|
||||||
if (initialPollId != null && model.id != initialPollId) {
|
if (initialPollId != null && model.id != initialPollId) {
|
||||||
notifier.setEditingId(initialPollId);
|
Future(() {
|
||||||
|
if (context.mounted) notifier.setEditingId(context, initialPollId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -437,6 +430,7 @@ class PollEditorScreen extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Form(
|
child: Form(
|
||||||
|
key: ValueKey(model.id),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
|
@@ -23,6 +23,7 @@ class PollSubmit extends ConsumerStatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.poll,
|
required this.poll,
|
||||||
required this.onSubmit,
|
required this.onSubmit,
|
||||||
|
required this.stats,
|
||||||
this.initialAnswers,
|
this.initialAnswers,
|
||||||
this.onCancel,
|
this.onCancel,
|
||||||
this.showProgress = true,
|
this.showProgress = true,
|
||||||
@@ -35,6 +36,7 @@ class PollSubmit extends ConsumerStatefulWidget {
|
|||||||
|
|
||||||
/// Optional initial answers, keyed by questionId.
|
/// Optional initial answers, keyed by questionId.
|
||||||
final Map<String, dynamic>? initialAnswers;
|
final Map<String, dynamic>? initialAnswers;
|
||||||
|
final Map<String, dynamic>? stats;
|
||||||
|
|
||||||
/// Optional cancel callback.
|
/// Optional cancel callback.
|
||||||
final VoidCallback? onCancel;
|
final VoidCallback? onCancel;
|
||||||
@@ -321,6 +323,153 @@ class _PollSubmitState extends ConsumerState<PollSubmit> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildStats(BuildContext context, SnPollQuestion q) {
|
||||||
|
if (widget.stats == null) return const SizedBox.shrink();
|
||||||
|
final raw = widget.stats![q.id];
|
||||||
|
if (raw == null) return const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget? body;
|
||||||
|
|
||||||
|
switch (q.type) {
|
||||||
|
case SnPollQuestionType.rating:
|
||||||
|
// rating: avg score (double or int)
|
||||||
|
final avg = (raw['rating'] as num).toDouble();
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
body = Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.star, color: Colors.amber.shade600, size: 18),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text(
|
||||||
|
avg.toStringAsFixed(1),
|
||||||
|
style: theme.textTheme.labelMedium?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SnPollQuestionType.yesNo:
|
||||||
|
// yes/no: map {true: count, false: count}
|
||||||
|
if (raw is Map) {
|
||||||
|
final int yes =
|
||||||
|
(raw[true] is int)
|
||||||
|
? raw[true] as int
|
||||||
|
: int.tryParse('${raw[true]}') ?? 0;
|
||||||
|
final int no =
|
||||||
|
(raw[false] is int)
|
||||||
|
? raw[false] as int
|
||||||
|
: int.tryParse('${raw[false]}') ?? 0;
|
||||||
|
final total = (yes + no).clamp(0, 1 << 31);
|
||||||
|
final yesPct = total == 0 ? 0.0 : yes / total;
|
||||||
|
final noPct = total == 0 ? 0.0 : no / total;
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
body = Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_BarStatRow(
|
||||||
|
label: 'Yes',
|
||||||
|
count: yes,
|
||||||
|
fraction: yesPct,
|
||||||
|
color: Colors.green.shade600,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
_BarStatRow(
|
||||||
|
label: 'No',
|
||||||
|
count: no,
|
||||||
|
fraction: noPct,
|
||||||
|
color: Colors.red.shade600,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'Total: $total',
|
||||||
|
style: theme.textTheme.labelSmall?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SnPollQuestionType.singleChoice:
|
||||||
|
case SnPollQuestionType.multipleChoice:
|
||||||
|
// map optionId -> count
|
||||||
|
if (raw is Map) {
|
||||||
|
final options = [...?q.options]
|
||||||
|
..sort((a, b) => a.order.compareTo(b.order));
|
||||||
|
final List<_OptionCount> items = [];
|
||||||
|
int total = 0;
|
||||||
|
for (final opt in options) {
|
||||||
|
final dynamic v = raw[opt.id];
|
||||||
|
final int count = v is int ? v : int.tryParse('$v') ?? 0;
|
||||||
|
total += count;
|
||||||
|
items.add(_OptionCount(id: opt.id, label: opt.label, count: count));
|
||||||
|
}
|
||||||
|
if (items.isNotEmpty) {
|
||||||
|
items.sort(
|
||||||
|
(a, b) => b.count.compareTo(a.count),
|
||||||
|
); // show highest first
|
||||||
|
}
|
||||||
|
body = Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
for (final it in items)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 6),
|
||||||
|
child: _BarStatRow(
|
||||||
|
label: it.label,
|
||||||
|
count: it.count,
|
||||||
|
fraction: total == 0 ? 0 : it.count / total,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (items.isNotEmpty)
|
||||||
|
Text(
|
||||||
|
'Total: $total',
|
||||||
|
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SnPollQuestionType.freeText:
|
||||||
|
// No stats
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body == null) return const SizedBox.shrink();
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.35),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Stats',
|
||||||
|
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
body,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildBody(BuildContext context) {
|
Widget _buildBody(BuildContext context) {
|
||||||
final q = _current;
|
final q = _current;
|
||||||
switch (q.type) {
|
switch (q.type) {
|
||||||
@@ -467,7 +616,13 @@ class _PollSubmitState extends ConsumerState<PollSubmit> {
|
|||||||
children: [
|
children: [
|
||||||
_buildHeader(context),
|
_buildHeader(context),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
_AnimatedStep(key: ValueKey(_current.id), child: _buildBody(context)),
|
_AnimatedStep(
|
||||||
|
key: ValueKey(_current.id),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [_buildBody(context), _buildStats(context, _current)],
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildNavBar(context),
|
_buildNavBar(context),
|
||||||
],
|
],
|
||||||
@@ -475,6 +630,77 @@ class _PollSubmitState extends ConsumerState<PollSubmit> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _OptionCount {
|
||||||
|
final String id;
|
||||||
|
final String label;
|
||||||
|
final int count;
|
||||||
|
const _OptionCount({
|
||||||
|
required this.id,
|
||||||
|
required this.label,
|
||||||
|
required this.count,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BarStatRow extends StatelessWidget {
|
||||||
|
const _BarStatRow({
|
||||||
|
required this.label,
|
||||||
|
required this.count,
|
||||||
|
required this.fraction,
|
||||||
|
this.color,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String label;
|
||||||
|
final int count;
|
||||||
|
final double fraction;
|
||||||
|
final Color? color;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final barColor = color ?? Theme.of(context).colorScheme.primary;
|
||||||
|
final bgColor = Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceVariant.withOpacity(0.6);
|
||||||
|
final fg =
|
||||||
|
(fraction.isNaN || fraction.isInfinite)
|
||||||
|
? 0.0
|
||||||
|
: fraction.clamp(0.0, 1.0);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('$label · $count', style: Theme.of(context).textTheme.labelMedium),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final width = constraints.maxWidth;
|
||||||
|
final filled = width * fg;
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 8,
|
||||||
|
width: width,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: bgColor,
|
||||||
|
borderRadius: BorderRadius.circular(999),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 8,
|
||||||
|
width: filled,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: barColor,
|
||||||
|
borderRadius: BorderRadius.circular(999),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Simple fade/slide transition between questions.
|
/// Simple fade/slide transition between questions.
|
||||||
class _AnimatedStep extends StatelessWidget {
|
class _AnimatedStep extends StatelessWidget {
|
||||||
const _AnimatedStep({super.key, required this.child});
|
const _AnimatedStep({super.key, required this.child});
|
||||||
|
@@ -566,9 +566,10 @@ class PostItem extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
child: PollSubmit(
|
child: PollSubmit(
|
||||||
initialAnswers: embedData['poll']?['user_answer']?['answer'],
|
initialAnswers: embedData['poll']?['user_answer']?['answer'],
|
||||||
|
stats: embedData['poll']?['stats'],
|
||||||
poll: SnPollWithStats.fromJson(embedData['poll']),
|
poll: SnPollWithStats.fromJson(embedData['poll']),
|
||||||
onSubmit: (_) {},
|
onSubmit: (_) {},
|
||||||
).padding(horizontal: 12, vertical: 8),
|
).padding(horizontal: 16, vertical: 12),
|
||||||
),
|
),
|
||||||
_ => const Placeholder(),
|
_ => const Placeholder(),
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user