Add back button on ticket and task detail screens

This commit is contained in:
Marc Rejohn Castillano 2026-03-03 18:15:18 +08:00
parent d9270b3edf
commit 1e678ea2e5
2 changed files with 101 additions and 77 deletions

View File

@ -2400,7 +2400,21 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
final detailsCard = Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(child: detailsContent),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
),
detailsContent,
],
),
),
),
);
@ -2605,67 +2619,67 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
),
);
if (isWide) {
return Row(
children: [
Expanded(flex: 2, child: detailsCard),
const SizedBox(width: 16),
Expanded(flex: 3, child: tabbedCard),
],
);
}
// Mobile/tablet: allow vertical scrolling of detail card while
// keeping the chat/activity panel filling the remaining viewport
// (and scrolling internally). Use a CustomScrollView to provide a
// bounded height for the tabbed card via SliverFillRemaining.
return Stack(
children: [
CustomScrollView(
slivers: [
SliverToBoxAdapter(child: detailsCard),
const SliverToBoxAdapter(child: SizedBox(height: 12)),
SliverFillRemaining(hasScrollBody: true, child: tabbedCard),
],
),
if (isRetrieving)
Positioned.fill(
child: AbsorbPointer(
absorbing: true,
child: Container(
color: Theme.of(
context,
).colorScheme.surface.withAlpha((0.35 * 255).round()),
alignment: Alignment.topCenter,
padding: const EdgeInsets.only(top: 36),
child: SizedBox(
width: 280,
child: Card(
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
final mainContent = isWide
? Row(
children: [
Expanded(flex: 2, child: detailsCard),
const SizedBox(width: 16),
Expanded(flex: 3, child: tabbedCard),
],
)
: Stack(
children: [
CustomScrollView(
slivers: [
SliverToBoxAdapter(child: detailsCard),
const SliverToBoxAdapter(child: SizedBox(height: 12)),
SliverFillRemaining(
hasScrollBody: true,
child: tabbedCard,
),
],
),
if (isRetrieving)
Positioned.fill(
child: AbsorbPointer(
absorbing: true,
child: Container(
color: Theme.of(context).colorScheme.surface
.withAlpha((0.35 * 255).round()),
alignment: Alignment.topCenter,
padding: const EdgeInsets.only(top: 36),
child: SizedBox(
width: 280,
child: Card(
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
SizedBox(width: 12),
Expanded(
child: Text('Retrieving updates…'),
),
],
),
),
SizedBox(width: 12),
Expanded(child: Text('Retrieving updates…')),
],
),
),
),
),
),
),
),
),
],
);
],
);
return mainContent;
},
),
),

View File

@ -199,7 +199,21 @@ class _TicketDetailScreenState extends ConsumerState<TicketDetailScreen> {
final detailsCard = Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(child: detailsContent),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
),
detailsContent,
],
),
),
),
);
@ -437,27 +451,23 @@ class _TicketDetailScreenState extends ConsumerState<TicketDetailScreen> {
),
);
if (isWide) {
return Row(
children: [
Expanded(flex: 2, child: detailsCard),
const SizedBox(width: 16),
Expanded(flex: 3, child: messagesCard),
],
);
}
final mainContent = isWide
? Row(
children: [
Expanded(flex: 2, child: detailsCard),
const SizedBox(width: 16),
Expanded(flex: 3, child: messagesCard),
],
)
: Column(
children: [
detailsCard,
const SizedBox(height: 12),
Expanded(child: messagesCard),
],
);
// Mobile: avoid nesting scrollables. detailsCard itself is
// scrollable if it grows tall, and the messages area takes the
// remaining space so the chat list can always receive touch
// gestures and never end up offscreen.
return Column(
children: [
detailsCard,
const SizedBox(height: 12),
Expanded(child: messagesCard),
],
);
return mainContent;
},
),
);