D1APP-53 messages ui
This commit is contained in:
parent
e2799e9786
commit
a0bb03f101
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:bot_toast/bot_toast.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/providers/server_data_provider.dart';
|
||||
import 'package:didvan/providers/theme_provider.dart';
|
||||
import 'package:didvan/providers/user_provider.dart';
|
||||
import 'package:didvan/routes/route_generator.dart';
|
||||
|
|
@ -24,9 +23,6 @@ class Didvan extends StatelessWidget {
|
|||
ChangeNotifierProvider<UserProvider>(
|
||||
create: (context) => UserProvider(),
|
||||
),
|
||||
ChangeNotifierProvider<ServerDataProvider>(
|
||||
create: (context) => ServerDataProvider(),
|
||||
),
|
||||
ChangeNotifierProvider<ThemeProvider>(
|
||||
create: (context) => ThemeProvider(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'package:didvan/models/category.dart';
|
||||
|
||||
class RadarAttachment {
|
||||
final int id;
|
||||
final String title;
|
||||
|
|
@ -5,6 +7,8 @@ class RadarAttachment {
|
|||
final int timeToRead;
|
||||
final String image;
|
||||
final bool forManagers;
|
||||
final String createdAt;
|
||||
final List<CategoryData> categories;
|
||||
|
||||
const RadarAttachment({
|
||||
required this.id,
|
||||
|
|
@ -13,6 +17,8 @@ class RadarAttachment {
|
|||
required this.timeToRead,
|
||||
required this.image,
|
||||
required this.forManagers,
|
||||
required this.categories,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory RadarAttachment.fromJson(Map<String, dynamic> json) =>
|
||||
|
|
@ -22,7 +28,13 @@ class RadarAttachment {
|
|||
description: json['description'],
|
||||
timeToRead: json['timeToRead'],
|
||||
image: json['image'],
|
||||
createdAt: json['createdAt'],
|
||||
forManagers: json['forManagers'],
|
||||
categories: List<CategoryData>.from(
|
||||
json['categories'].map(
|
||||
(cat) => CategoryData.fromJson(cat),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
import 'package:didvan/pages/home/direct/direct_state.dart';
|
||||
import 'package:didvan/pages/home/direct/widgets/message_box.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/widgets/didvan/scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Direct extends StatefulWidget {
|
||||
final int id;
|
||||
const Direct({Key? key, required this.id}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Direct> createState() => _DirectState();
|
||||
}
|
||||
|
||||
class _DirectState extends State<Direct> {
|
||||
@override
|
||||
void initState() {
|
||||
Future.delayed(Duration.zero, () {
|
||||
context.read<DirectState>().getMessages(widget.id);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
bottom: 56,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: DidvanScaffold(
|
||||
appBarData: AppBarData(
|
||||
hasBack: true,
|
||||
subtitle: 'ارتباط با سردبیر',
|
||||
title: 'رادار اقتصادی',
|
||||
),
|
||||
slivers: const [],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: const MessageBox(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/message_data/message_data.dart';
|
||||
import 'package:didvan/providers/core_provider.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
|
|
@ -9,15 +11,35 @@ import 'package:record/record.dart';
|
|||
|
||||
class DirectState extends CoreProvier {
|
||||
final _recorder = Record();
|
||||
final List<MessageData> messages = [];
|
||||
late final int typeId;
|
||||
final Map<String, List<int>> dailyMessages = {};
|
||||
|
||||
File? recordedFile;
|
||||
|
||||
bool isRecording = false;
|
||||
|
||||
Future<void> getMessages(int id) async {
|
||||
final RequestService service = RequestService(RequestHelper.direct(id));
|
||||
Future<void> getMessages() async {
|
||||
appState = AppState.busy;
|
||||
final RequestService service = RequestService(RequestHelper.direct(typeId));
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {}
|
||||
if (service.isSuccess) {
|
||||
final messageDatas = service.result['messages'];
|
||||
for (var i = 0; i < messageDatas.length; i++) {
|
||||
messages.add(MessageData.fromJson(messageDatas[i]));
|
||||
final createdAt = messages.last.createdAt.split('T').first;
|
||||
if (!dailyMessages.containsKey(createdAt)) {
|
||||
dailyMessages.addAll({
|
||||
createdAt: [messages.last.id]
|
||||
});
|
||||
} else {
|
||||
dailyMessages[createdAt]!.add(messages.last.id);
|
||||
}
|
||||
}
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
void deleteRecordedFile() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/pages/home/direct/direct_state.dart';
|
||||
import 'package:didvan/pages/home/direct/widgets/message.dart';
|
||||
import 'package:didvan/pages/home/direct/widgets/message_box.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/providers/server_data_provider.dart';
|
||||
import 'package:didvan/widgets/didvan/scaffold.dart';
|
||||
import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Direct extends StatefulWidget {
|
||||
final Map<String, dynamic> pageData;
|
||||
const Direct({Key? key, required this.pageData}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Direct> createState() => _DirectState();
|
||||
}
|
||||
|
||||
class _DirectState extends State<Direct> {
|
||||
@override
|
||||
void initState() {
|
||||
final state = context.read<DirectState>();
|
||||
final typeId = ServerDataProvider.labelToTypeId(widget.pageData['type']);
|
||||
state.typeId = typeId;
|
||||
Future.delayed(Duration.zero, () {
|
||||
state.getMessages();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = context.watch<DirectState>();
|
||||
final d = MediaQuery.of(context);
|
||||
return Material(
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
bottom: 56,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: DidvanScaffold(
|
||||
reverse: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
appBarData: AppBarData(
|
||||
hasBack: true,
|
||||
subtitle: 'ارتباط با سردبیر',
|
||||
title: widget.pageData['type'].substring(7),
|
||||
),
|
||||
slivers: [
|
||||
if (state.appState != AppState.busy)
|
||||
SliverStateHandler<DirectState>(
|
||||
itemPadding: const EdgeInsets.only(bottom: 12),
|
||||
state: state,
|
||||
builder: (context, state, index) => Message(
|
||||
message: state.messages[index],
|
||||
),
|
||||
childCount: state.messages.length,
|
||||
onRetry: state.getMessages,
|
||||
),
|
||||
],
|
||||
children: [
|
||||
if (state.appState == AppState.busy)
|
||||
SizedBox(
|
||||
height: d.size.height - kToolbarHeight - d.padding.top,
|
||||
child: Center(
|
||||
child: SpinKitSpinningLines(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: d.viewInsets.bottom,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: const MessageBox(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/models/message_data/message_data.dart';
|
||||
import 'package:didvan/pages/home/direct/direct_state.dart';
|
||||
import 'package:didvan/utils/date_time.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:didvan/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:persian_number_utility/persian_number_utility.dart';
|
||||
|
||||
class Message extends StatelessWidget {
|
||||
final MessageData message;
|
||||
const Message({Key? key, required this.message}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: message.writedByAdmin ? 20 : 0,
|
||||
left: !message.writedByAdmin ? 20 : 0,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
if (message.id ==
|
||||
context
|
||||
.read<DirectState>()
|
||||
.dailyMessages[message.createdAt.split('T').first]!
|
||||
.last)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.splash,
|
||||
borderRadius: DesignConfig.lowBorderRadius,
|
||||
),
|
||||
child: DidvanText(
|
||||
DateTime.parse(message.createdAt).toPersianDateStr(),
|
||||
style: Theme.of(context).textTheme.overline,
|
||||
color: DesignConfig.isDark
|
||||
? Theme.of(context).colorScheme.white
|
||||
: Theme.of(context).colorScheme.black,
|
||||
),
|
||||
),
|
||||
_MessageContainer(
|
||||
isAttachment: false,
|
||||
writedByAdmin: message.writedByAdmin,
|
||||
child:
|
||||
message.text != null ? DidvanText(message.text!) : Container(),
|
||||
),
|
||||
if (message.radar != null)
|
||||
DidvanText(
|
||||
'لینک به مطلب زیر:',
|
||||
style: Theme.of(context).textTheme.overline,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
if (message.radar != null) const SizedBox(height: 4),
|
||||
if (message.radar != null) _ReplyRadarOverview(message: message),
|
||||
if (message.radar != null) const SizedBox(height: 4),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ReplyRadarOverview extends StatelessWidget {
|
||||
final MessageData message;
|
||||
const _ReplyRadarOverview({Key? key, required this.message})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _MessageContainer(
|
||||
writedByAdmin: message.writedByAdmin,
|
||||
isAttachment: true,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SkeletonImage(
|
||||
imageUrl: message.radar!.image,
|
||||
height: 80,
|
||||
width: 80,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 80,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
DidvanText(
|
||||
message.radar!.title,
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
DidvanText(
|
||||
'رادار ' + message.radar!.categories.first.label,
|
||||
style: Theme.of(context).textTheme.overline,
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
),
|
||||
const Spacer(),
|
||||
DidvanText(
|
||||
DateTimeUtils.momentGenerator(
|
||||
message.radar!.createdAt) +
|
||||
' | خواندن در ' +
|
||||
message.radar!.timeToRead.toString() +
|
||||
' دقیقه',
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
style: Theme.of(context).textTheme.overline,
|
||||
),
|
||||
// DidvanText('text'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MessageContainer extends StatelessWidget {
|
||||
final bool writedByAdmin;
|
||||
final bool isAttachment;
|
||||
final Widget child;
|
||||
const _MessageContainer({
|
||||
Key? key,
|
||||
required this.writedByAdmin,
|
||||
required this.isAttachment,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: DesignConfig.highBorderRadius.copyWith(
|
||||
bottomLeft: writedByAdmin && !isAttachment ? Radius.zero : null,
|
||||
bottomRight: !writedByAdmin && !isAttachment ? Radius.zero : null,
|
||||
),
|
||||
color: writedByAdmin ? null : Theme.of(context).colorScheme.focused,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.border,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:didvan/config/theme_data.dart';
|
|||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/chat_room/chat_room.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/utils/date_time.dart';
|
||||
import 'package:didvan/widgets/didvan/badge.dart';
|
||||
import 'package:didvan/widgets/didvan/divider.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
|
|
@ -16,7 +17,7 @@ class ChatRoomItem extends StatelessWidget {
|
|||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.direct,
|
||||
arguments: chatRoom.id,
|
||||
arguments: {'type': chatRoom.type},
|
||||
),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
|
|
@ -35,15 +36,18 @@ class ChatRoomItem extends StatelessWidget {
|
|||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
),
|
||||
DidvanBadge(text: chatRoom.unread.toString()),
|
||||
if (chatRoom.unread != 0)
|
||||
DidvanBadge(text: chatRoom.unread.toString()),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 40),
|
||||
const Icon(
|
||||
DidvanIcons.check_double_light,
|
||||
Icon(
|
||||
chatRoom.lastMessage.readed
|
||||
? DidvanIcons.check_double_light
|
||||
: DidvanIcons.check_light,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
|
|
@ -54,9 +58,10 @@ class ChatRoomItem extends StatelessWidget {
|
|||
DidvanText(
|
||||
chatRoom.lastMessage.text ?? '',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
DidvanText(
|
||||
chatRoom.updatedAt,
|
||||
DateTimeUtils.momentGenerator(chatRoom.updatedAt),
|
||||
style: Theme.of(context).textTheme.caption,
|
||||
color: Theme.of(context).colorScheme.caption,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class _SplashState extends State<Splash> {
|
|||
log(token);
|
||||
RequestService.token = token;
|
||||
await userProvider.getUserInfo();
|
||||
await context.read<ServerDataProvider>().getData();
|
||||
ServerDataProvider.getData();
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed(
|
||||
token == null ? Routes.authenticaion : Routes.home,
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
import 'package:didvan/providers/core_provider.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
|
||||
class ServerDataProvider extends CoreProvier {
|
||||
final List<MapEntry> directTypes = [];
|
||||
class ServerDataProvider {
|
||||
static final List<MapEntry> directTypes = [];
|
||||
|
||||
Future<void> getData() async {
|
||||
static Future<void> getData() async {
|
||||
await _getDirectTypes();
|
||||
}
|
||||
|
||||
Future<void> _getDirectTypes() async {
|
||||
static int labelToTypeId(String label) =>
|
||||
directTypes.firstWhere((element) => element.value == label).key;
|
||||
|
||||
static Future<void> _getDirectTypes() async {
|
||||
final service = RequestService(RequestHelper.directTypes);
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:didvan/pages/authentication/authentication.dart';
|
|||
import 'package:didvan/pages/authentication/authentication_state.dart';
|
||||
import 'package:didvan/pages/home/comments/comments.dart';
|
||||
import 'package:didvan/pages/home/comments/comments_state.dart';
|
||||
import 'package:didvan/pages/home/direct/direct.dart';
|
||||
import 'package:didvan/pages/home/direct/widgets/direct.dart';
|
||||
import 'package:didvan/pages/home/direct/direct_state.dart';
|
||||
import 'package:didvan/pages/home/home.dart';
|
||||
import 'package:didvan/pages/home/home_state.dart';
|
||||
|
|
@ -109,7 +109,7 @@ class RouteGenerator {
|
|||
return _createRoute(
|
||||
ChangeNotifierProvider<DirectState>(
|
||||
create: (context) => DirectState(),
|
||||
child: Direct(id: settings.arguments as int),
|
||||
child: Direct(pageData: settings.arguments as Map<String, dynamic>),
|
||||
),
|
||||
);
|
||||
case Routes.comments:
|
||||
|
|
|
|||
|
|
@ -19,11 +19,17 @@ class RequestHelper {
|
|||
|
||||
static const String directTypes = baseUrl + '/direct/types';
|
||||
static String direct(int id) => _baseUserUrl + '/direct/$id';
|
||||
static String tag(List<int> ids) =>
|
||||
static String tag({
|
||||
required List<int> ids,
|
||||
required String type,
|
||||
required int itemId,
|
||||
}) =>
|
||||
baseUrl +
|
||||
'/tag' +
|
||||
_urlConcatGenerator([
|
||||
const MapEntry('limit', '3'),
|
||||
MapEntry('type', type),
|
||||
MapEntry('id', itemId.toString()),
|
||||
MapEntry('tags', _urlListConcatGenerator(ids))
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ class DateTimeUtils {
|
|||
}
|
||||
interval = seconds / 86400;
|
||||
if (interval > 1) {
|
||||
if (interval.floor() == 1) return 'دیروز';
|
||||
return interval.floor().toString() + " روز پیش";
|
||||
}
|
||||
interval = seconds / 3600;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,31 @@ import 'package:flutter/material.dart';
|
|||
|
||||
class DidvanAppBar extends StatelessWidget {
|
||||
final AppBarData appBarData;
|
||||
const DidvanAppBar({Key? key, required this.appBarData}) : super(key: key);
|
||||
final bool hasBorder;
|
||||
final Color? backgroundColor;
|
||||
const DidvanAppBar({
|
||||
Key? key,
|
||||
required this.appBarData,
|
||||
this.hasBorder = false,
|
||||
this.backgroundColor = Colors.transparent,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
return Container(
|
||||
height: kToolbarHeight + MediaQuery.of(context).padding.top,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
padding: const EdgeInsets.only(right: 4, left: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
border: hasBorder
|
||||
? Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).colorScheme.cardBorder,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ import 'package:didvan/models/view/app_bar_data.dart';
|
|||
import 'package:didvan/widgets/didvan/app_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DidvanScaffold extends StatelessWidget {
|
||||
class DidvanScaffold extends StatefulWidget {
|
||||
final List<Widget>? slivers;
|
||||
final List<Widget>? children;
|
||||
final AppBarData appBarData;
|
||||
final EdgeInsets padding;
|
||||
final Color? backgroundColor;
|
||||
final bool reverse;
|
||||
|
||||
const DidvanScaffold({
|
||||
Key? key,
|
||||
this.slivers,
|
||||
|
|
@ -15,47 +17,120 @@ class DidvanScaffold extends StatelessWidget {
|
|||
this.children,
|
||||
this.padding = const EdgeInsets.symmetric(horizontal: 16),
|
||||
this.backgroundColor,
|
||||
this.reverse = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<DidvanScaffold> createState() => _DidvanScaffoldState();
|
||||
}
|
||||
|
||||
class _DidvanScaffoldState extends State<DidvanScaffold> {
|
||||
final _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double statusBarHeight = MediaQuery.of(context).padding.top;
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
backgroundColor: widget.backgroundColor,
|
||||
body: Padding(
|
||||
padding: EdgeInsets.only(top: statusBarHeight),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
toolbarHeight: kToolbarHeight,
|
||||
backgroundColor:
|
||||
backgroundColor ?? Theme.of(context).colorScheme.background,
|
||||
automaticallyImplyLeading: false,
|
||||
pinned: true,
|
||||
flexibleSpace: DidvanAppBar(appBarData: appBarData),
|
||||
),
|
||||
const SliverToBoxAdapter(
|
||||
child: SizedBox(height: 16),
|
||||
),
|
||||
if (children != null)
|
||||
SliverPadding(
|
||||
padding: padding,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => children![index],
|
||||
childCount: children!.length,
|
||||
child: Stack(
|
||||
children: [
|
||||
CustomScrollView(
|
||||
controller: _scrollController,
|
||||
reverse: widget.reverse,
|
||||
slivers: [
|
||||
if (!widget.reverse)
|
||||
SliverAppBar(
|
||||
toolbarHeight: kToolbarHeight,
|
||||
backgroundColor: widget.backgroundColor ??
|
||||
Theme.of(context).colorScheme.background,
|
||||
automaticallyImplyLeading: false,
|
||||
pinned: true,
|
||||
flexibleSpace: DidvanAppBar(appBarData: widget.appBarData),
|
||||
),
|
||||
),
|
||||
if (!widget.reverse)
|
||||
const SliverToBoxAdapter(
|
||||
child: SizedBox(height: 16),
|
||||
),
|
||||
if (widget.children != null)
|
||||
SliverPadding(
|
||||
padding: widget.padding,
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) => widget.children![index],
|
||||
childCount: widget.children!.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.slivers != null)
|
||||
for (var i = 0; i < widget.slivers!.length; i++)
|
||||
SliverPadding(
|
||||
padding: widget.padding,
|
||||
sliver: widget.slivers![i],
|
||||
),
|
||||
if (widget.reverse)
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: kToolbarHeight +
|
||||
MediaQuery.of(context).padding.top +
|
||||
12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.reverse)
|
||||
_AppBar(
|
||||
appBarData: widget.appBarData,
|
||||
scrollController: _scrollController,
|
||||
),
|
||||
if (slivers != null)
|
||||
for (var i = 0; i < slivers!.length; i++)
|
||||
SliverPadding(
|
||||
padding: padding,
|
||||
sliver: slivers![i],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AppBar extends StatefulWidget {
|
||||
final AppBarData appBarData;
|
||||
final ScrollController scrollController;
|
||||
const _AppBar({
|
||||
Key? key,
|
||||
required this.appBarData,
|
||||
required this.scrollController,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
__AppBarState createState() => __AppBarState();
|
||||
}
|
||||
|
||||
class __AppBarState extends State<_AppBar> {
|
||||
bool _isScrolled = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
widget.scrollController.addListener(() {
|
||||
final position = widget.scrollController.position.pixels;
|
||||
if (position > 10 && _isScrolled == false) {
|
||||
setState(() {
|
||||
_isScrolled = true;
|
||||
});
|
||||
}
|
||||
if (position < 10 && _isScrolled == true) {
|
||||
setState(() {
|
||||
_isScrolled = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DidvanAppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
appBarData: widget.appBarData,
|
||||
hasBorder: _isScrolled,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue