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:bot_toast/bot_toast.dart';
|
||||||
import 'package:didvan/config/theme_data.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/theme_provider.dart';
|
||||||
import 'package:didvan/providers/user_provider.dart';
|
import 'package:didvan/providers/user_provider.dart';
|
||||||
import 'package:didvan/routes/route_generator.dart';
|
import 'package:didvan/routes/route_generator.dart';
|
||||||
|
|
@ -24,9 +23,6 @@ class Didvan extends StatelessWidget {
|
||||||
ChangeNotifierProvider<UserProvider>(
|
ChangeNotifierProvider<UserProvider>(
|
||||||
create: (context) => UserProvider(),
|
create: (context) => UserProvider(),
|
||||||
),
|
),
|
||||||
ChangeNotifierProvider<ServerDataProvider>(
|
|
||||||
create: (context) => ServerDataProvider(),
|
|
||||||
),
|
|
||||||
ChangeNotifierProvider<ThemeProvider>(
|
ChangeNotifierProvider<ThemeProvider>(
|
||||||
create: (context) => ThemeProvider(),
|
create: (context) => ThemeProvider(),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:didvan/models/category.dart';
|
||||||
|
|
||||||
class RadarAttachment {
|
class RadarAttachment {
|
||||||
final int id;
|
final int id;
|
||||||
final String title;
|
final String title;
|
||||||
|
|
@ -5,6 +7,8 @@ class RadarAttachment {
|
||||||
final int timeToRead;
|
final int timeToRead;
|
||||||
final String image;
|
final String image;
|
||||||
final bool forManagers;
|
final bool forManagers;
|
||||||
|
final String createdAt;
|
||||||
|
final List<CategoryData> categories;
|
||||||
|
|
||||||
const RadarAttachment({
|
const RadarAttachment({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
|
@ -13,6 +17,8 @@ class RadarAttachment {
|
||||||
required this.timeToRead,
|
required this.timeToRead,
|
||||||
required this.image,
|
required this.image,
|
||||||
required this.forManagers,
|
required this.forManagers,
|
||||||
|
required this.categories,
|
||||||
|
required this.createdAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory RadarAttachment.fromJson(Map<String, dynamic> json) =>
|
factory RadarAttachment.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|
@ -22,7 +28,13 @@ class RadarAttachment {
|
||||||
description: json['description'],
|
description: json['description'],
|
||||||
timeToRead: json['timeToRead'],
|
timeToRead: json['timeToRead'],
|
||||||
image: json['image'],
|
image: json['image'],
|
||||||
|
createdAt: json['createdAt'],
|
||||||
forManagers: json['forManagers'],
|
forManagers: json['forManagers'],
|
||||||
|
categories: List<CategoryData>.from(
|
||||||
|
json['categories'].map(
|
||||||
|
(cat) => CategoryData.fromJson(cat),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
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 '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/providers/core_provider.dart';
|
||||||
import 'package:didvan/services/network/request.dart';
|
import 'package:didvan/services/network/request.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
|
|
@ -9,15 +11,35 @@ import 'package:record/record.dart';
|
||||||
|
|
||||||
class DirectState extends CoreProvier {
|
class DirectState extends CoreProvier {
|
||||||
final _recorder = Record();
|
final _recorder = Record();
|
||||||
|
final List<MessageData> messages = [];
|
||||||
|
late final int typeId;
|
||||||
|
final Map<String, List<int>> dailyMessages = {};
|
||||||
|
|
||||||
File? recordedFile;
|
File? recordedFile;
|
||||||
|
|
||||||
bool isRecording = false;
|
bool isRecording = false;
|
||||||
|
|
||||||
Future<void> getMessages(int id) async {
|
Future<void> getMessages() async {
|
||||||
final RequestService service = RequestService(RequestHelper.direct(id));
|
appState = AppState.busy;
|
||||||
|
final RequestService service = RequestService(RequestHelper.direct(typeId));
|
||||||
await service.httpGet();
|
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() {
|
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/constants/app_icons.dart';
|
||||||
import 'package:didvan/models/chat_room/chat_room.dart';
|
import 'package:didvan/models/chat_room/chat_room.dart';
|
||||||
import 'package:didvan/routes/routes.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/badge.dart';
|
||||||
import 'package:didvan/widgets/didvan/divider.dart';
|
import 'package:didvan/widgets/didvan/divider.dart';
|
||||||
import 'package:didvan/widgets/didvan/text.dart';
|
import 'package:didvan/widgets/didvan/text.dart';
|
||||||
|
|
@ -16,7 +17,7 @@ class ChatRoomItem extends StatelessWidget {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => Navigator.of(context).pushNamed(
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
Routes.direct,
|
Routes.direct,
|
||||||
arguments: chatRoom.id,
|
arguments: {'type': chatRoom.type},
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
|
|
@ -35,15 +36,18 @@ class ChatRoomItem extends StatelessWidget {
|
||||||
style: Theme.of(context).textTheme.bodyText1,
|
style: Theme.of(context).textTheme.bodyText1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DidvanBadge(text: chatRoom.unread.toString()),
|
if (chatRoom.unread != 0)
|
||||||
|
DidvanBadge(text: chatRoom.unread.toString()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(width: 40),
|
const SizedBox(width: 40),
|
||||||
const Icon(
|
Icon(
|
||||||
DidvanIcons.check_double_light,
|
chatRoom.lastMessage.readed
|
||||||
|
? DidvanIcons.check_double_light
|
||||||
|
: DidvanIcons.check_light,
|
||||||
size: 16,
|
size: 16,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
|
|
@ -54,9 +58,10 @@ class ChatRoomItem extends StatelessWidget {
|
||||||
DidvanText(
|
DidvanText(
|
||||||
chatRoom.lastMessage.text ?? '',
|
chatRoom.lastMessage.text ?? '',
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
DidvanText(
|
DidvanText(
|
||||||
chatRoom.updatedAt,
|
DateTimeUtils.momentGenerator(chatRoom.updatedAt),
|
||||||
style: Theme.of(context).textTheme.caption,
|
style: Theme.of(context).textTheme.caption,
|
||||||
color: Theme.of(context).colorScheme.caption,
|
color: Theme.of(context).colorScheme.caption,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ class _SplashState extends State<Splash> {
|
||||||
log(token);
|
log(token);
|
||||||
RequestService.token = token;
|
RequestService.token = token;
|
||||||
await userProvider.getUserInfo();
|
await userProvider.getUserInfo();
|
||||||
await context.read<ServerDataProvider>().getData();
|
ServerDataProvider.getData();
|
||||||
}
|
}
|
||||||
Navigator.of(context).pushReplacementNamed(
|
Navigator.of(context).pushReplacementNamed(
|
||||||
token == null ? Routes.authenticaion : Routes.home,
|
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.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
|
|
||||||
class ServerDataProvider extends CoreProvier {
|
class ServerDataProvider {
|
||||||
final List<MapEntry> directTypes = [];
|
static final List<MapEntry> directTypes = [];
|
||||||
|
|
||||||
Future<void> getData() async {
|
static Future<void> getData() async {
|
||||||
await _getDirectTypes();
|
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);
|
final service = RequestService(RequestHelper.directTypes);
|
||||||
await service.httpGet();
|
await service.httpGet();
|
||||||
if (service.isSuccess) {
|
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/authentication/authentication_state.dart';
|
||||||
import 'package:didvan/pages/home/comments/comments.dart';
|
import 'package:didvan/pages/home/comments/comments.dart';
|
||||||
import 'package:didvan/pages/home/comments/comments_state.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/direct/direct_state.dart';
|
||||||
import 'package:didvan/pages/home/home.dart';
|
import 'package:didvan/pages/home/home.dart';
|
||||||
import 'package:didvan/pages/home/home_state.dart';
|
import 'package:didvan/pages/home/home_state.dart';
|
||||||
|
|
@ -109,7 +109,7 @@ class RouteGenerator {
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<DirectState>(
|
ChangeNotifierProvider<DirectState>(
|
||||||
create: (context) => DirectState(),
|
create: (context) => DirectState(),
|
||||||
child: Direct(id: settings.arguments as int),
|
child: Direct(pageData: settings.arguments as Map<String, dynamic>),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case Routes.comments:
|
case Routes.comments:
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,17 @@ class RequestHelper {
|
||||||
|
|
||||||
static const String directTypes = baseUrl + '/direct/types';
|
static const String directTypes = baseUrl + '/direct/types';
|
||||||
static String direct(int id) => _baseUserUrl + '/direct/$id';
|
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 +
|
baseUrl +
|
||||||
'/tag' +
|
'/tag' +
|
||||||
_urlConcatGenerator([
|
_urlConcatGenerator([
|
||||||
const MapEntry('limit', '3'),
|
const MapEntry('limit', '3'),
|
||||||
|
MapEntry('type', type),
|
||||||
|
MapEntry('id', itemId.toString()),
|
||||||
MapEntry('tags', _urlListConcatGenerator(ids))
|
MapEntry('tags', _urlListConcatGenerator(ids))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ class DateTimeUtils {
|
||||||
}
|
}
|
||||||
interval = seconds / 86400;
|
interval = seconds / 86400;
|
||||||
if (interval > 1) {
|
if (interval > 1) {
|
||||||
|
if (interval.floor() == 1) return 'دیروز';
|
||||||
return interval.floor().toString() + " روز پیش";
|
return interval.floor().toString() + " روز پیش";
|
||||||
}
|
}
|
||||||
interval = seconds / 3600;
|
interval = seconds / 3600;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,31 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DidvanAppBar extends StatelessWidget {
|
class DidvanAppBar extends StatelessWidget {
|
||||||
final AppBarData appBarData;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
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),
|
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(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,14 @@ import 'package:didvan/models/view/app_bar_data.dart';
|
||||||
import 'package:didvan/widgets/didvan/app_bar.dart';
|
import 'package:didvan/widgets/didvan/app_bar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DidvanScaffold extends StatelessWidget {
|
class DidvanScaffold extends StatefulWidget {
|
||||||
final List<Widget>? slivers;
|
final List<Widget>? slivers;
|
||||||
final List<Widget>? children;
|
final List<Widget>? children;
|
||||||
final AppBarData appBarData;
|
final AppBarData appBarData;
|
||||||
final EdgeInsets padding;
|
final EdgeInsets padding;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
|
final bool reverse;
|
||||||
|
|
||||||
const DidvanScaffold({
|
const DidvanScaffold({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.slivers,
|
this.slivers,
|
||||||
|
|
@ -15,47 +17,120 @@ class DidvanScaffold extends StatelessWidget {
|
||||||
this.children,
|
this.children,
|
||||||
this.padding = const EdgeInsets.symmetric(horizontal: 16),
|
this.padding = const EdgeInsets.symmetric(horizontal: 16),
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
|
this.reverse = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DidvanScaffold> createState() => _DidvanScaffoldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DidvanScaffoldState extends State<DidvanScaffold> {
|
||||||
|
final _scrollController = ScrollController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final double statusBarHeight = MediaQuery.of(context).padding.top;
|
final double statusBarHeight = MediaQuery.of(context).padding.top;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: widget.backgroundColor,
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: EdgeInsets.only(top: statusBarHeight),
|
padding: EdgeInsets.only(top: statusBarHeight),
|
||||||
child: CustomScrollView(
|
child: Stack(
|
||||||
slivers: [
|
children: [
|
||||||
SliverAppBar(
|
CustomScrollView(
|
||||||
toolbarHeight: kToolbarHeight,
|
controller: _scrollController,
|
||||||
backgroundColor:
|
reverse: widget.reverse,
|
||||||
backgroundColor ?? Theme.of(context).colorScheme.background,
|
slivers: [
|
||||||
automaticallyImplyLeading: false,
|
if (!widget.reverse)
|
||||||
pinned: true,
|
SliverAppBar(
|
||||||
flexibleSpace: DidvanAppBar(appBarData: appBarData),
|
toolbarHeight: kToolbarHeight,
|
||||||
),
|
backgroundColor: widget.backgroundColor ??
|
||||||
const SliverToBoxAdapter(
|
Theme.of(context).colorScheme.background,
|
||||||
child: SizedBox(height: 16),
|
automaticallyImplyLeading: false,
|
||||||
),
|
pinned: true,
|
||||||
if (children != null)
|
flexibleSpace: DidvanAppBar(appBarData: widget.appBarData),
|
||||||
SliverPadding(
|
|
||||||
padding: padding,
|
|
||||||
sliver: SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) => children![index],
|
|
||||||
childCount: children!.length,
|
|
||||||
),
|
),
|
||||||
),
|
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