Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
ChatGPT
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
关振斌
ChatGPT
Commits
c7740f49
Commit
c7740f49
authored
Feb 20, 2023
by
关振斌
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chat
parent
a36cde6a
Changes
61
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
61 changed files
with
3170 additions
and
273 deletions
+3170
-273
ios/Podfile.lock
ios/Podfile.lock
+6
-0
lib/common/apis/news.dart
lib/common/apis/news.dart
+9
-0
lib/common/entities/classFyDetail.dart
lib/common/entities/classFyDetail.dart
+4
-0
lib/common/store/user.dart
lib/common/store/user.dart
+3
-3
lib/common/values/server.dart
lib/common/values/server.dart
+4
-2
lib/common/widgets/app.dart
lib/common/widgets/app.dart
+1
-1
lib/entity/plan_entity.dart
lib/entity/plan_entity.dart
+6
-1
lib/package/chat_dash/dash_chat_2.dart
lib/package/chat_dash/dash_chat_2.dart
+48
-0
lib/package/chat_dash/src/dash_chat.dart
lib/package/chat_dash/src/dash_chat.dart
+73
-0
lib/package/chat_dash/src/models/chat_media.dart
lib/package/chat_dash/src/models/chat_media.dart
+84
-0
lib/package/chat_dash/src/models/chat_message.dart
lib/package/chat_dash/src/models/chat_message.dart
+122
-0
lib/package/chat_dash/src/models/chat_user.dart
lib/package/chat_dash/src/models/chat_user.dart
+61
-0
lib/package/chat_dash/src/models/cursor_style.dart
lib/package/chat_dash/src/models/cursor_style.dart
+19
-0
lib/package/chat_dash/src/models/input_options.dart
lib/package/chat_dash/src/models/input_options.dart
+110
-0
lib/package/chat_dash/src/models/mention.dart
lib/package/chat_dash/src/models/mention.dart
+33
-0
lib/package/chat_dash/src/models/message_list_options.dart
lib/package/chat_dash/src/models/message_list_options.dart
+57
-0
lib/package/chat_dash/src/models/message_options.dart
lib/package/chat_dash/src/models/message_options.dart
+151
-0
lib/package/chat_dash/src/models/quick_reply.dart
lib/package/chat_dash/src/models/quick_reply.dart
+41
-0
lib/package/chat_dash/src/models/quick_reply_options.dart
lib/package/chat_dash/src/models/quick_reply_options.dart
+32
-0
lib/package/chat_dash/src/models/scroll_to_bottom_options.dart
...ackage/chat_dash/src/models/scroll_to_bottom_options.dart
+22
-0
lib/package/chat_dash/src/widgets/image_provider/image_provider.dart
.../chat_dash/src/widgets/image_provider/image_provider.dart
+2
-0
lib/package/chat_dash/src/widgets/image_provider/image_provider_mobile.dart
...ash/src/widgets/image_provider/image_provider_mobile.dart
+16
-0
lib/package/chat_dash/src/widgets/image_provider/image_provider_web.dart
...t_dash/src/widgets/image_provider/image_provider_web.dart
+12
-0
lib/package/chat_dash/src/widgets/input_toolbar/default_input_decoration.dart
...h/src/widgets/input_toolbar/default_input_decoration.dart
+78
-0
lib/package/chat_dash/src/widgets/input_toolbar/default_send_button.dart
...t_dash/src/widgets/input_toolbar/default_send_button.dart
+19
-0
lib/package/chat_dash/src/widgets/input_toolbar/input_toolbar.dart
...ge/chat_dash/src/widgets/input_toolbar/input_toolbar.dart
+237
-0
lib/package/chat_dash/src/widgets/message_list/default_date_separator.dart
...dash/src/widgets/message_list/default_date_separator.dart
+58
-0
lib/package/chat_dash/src/widgets/message_list/default_scroll_to_bottom.dart
...sh/src/widgets/message_list/default_scroll_to_bottom.dart
+95
-0
lib/package/chat_dash/src/widgets/message_list/message_list.dart
...kage/chat_dash/src/widgets/message_list/message_list.dart
+249
-0
lib/package/chat_dash/src/widgets/message_row/default_avatar.dart
...age/chat_dash/src/widgets/message_row/default_avatar.dart
+98
-0
lib/package/chat_dash/src/widgets/message_row/default_message_decoration.dart
...h/src/widgets/message_row/default_message_decoration.dart
+19
-0
lib/package/chat_dash/src/widgets/message_row/default_message_text.dart
...at_dash/src/widgets/message_row/default_message_text.dart
+158
-0
lib/package/chat_dash/src/widgets/message_row/default_parse_patterns.dart
..._dash/src/widgets/message_row/default_parse_patterns.dart
+17
-0
lib/package/chat_dash/src/widgets/message_row/default_user_name.dart
.../chat_dash/src/widgets/message_row/default_user_name.dart
+35
-0
lib/package/chat_dash/src/widgets/message_row/media_container.dart
...ge/chat_dash/src/widgets/message_row/media_container.dart
+146
-0
lib/package/chat_dash/src/widgets/message_row/message_row.dart
...ackage/chat_dash/src/widgets/message_row/message_row.dart
+168
-0
lib/package/chat_dash/src/widgets/message_row/text_container.dart
...age/chat_dash/src/widgets/message_row/text_container.dart
+93
-0
lib/package/chat_dash/src/widgets/message_row/video_player.dart
...ckage/chat_dash/src/widgets/message_row/video_player.dart
+81
-0
lib/package/chat_dash/src/widgets/quick_replies/default_quick_reply.dart
...t_dash/src/widgets/quick_replies/default_quick_reply.dart
+41
-0
lib/package/chat_dash/src/widgets/quick_replies/quick_replies.dart
...ge/chat_dash/src/widgets/quick_replies/quick_replies.dart
+42
-0
lib/package/chat_dash/src/widgets/typing_users/default_typing_builder.dart
...dash/src/widgets/typing_users/default_typing_builder.dart
+43
-0
lib/package/chat_dash/src/widgets/typing_users/typing_indicator.dart
.../chat_dash/src/widgets/typing_users/typing_indicator.dart
+82
-0
lib/pages/application/controller.dart
lib/pages/application/controller.dart
+5
-2
lib/pages/frame/notfound/controller.dart
lib/pages/frame/notfound/controller.dart
+9
-9
lib/pages/frame/notfound/state.dart
lib/pages/frame/notfound/state.dart
+3
-3
lib/pages/frame/notfound/view.dart
lib/pages/frame/notfound/view.dart
+88
-9
lib/pages/frame/product/controller.dart
lib/pages/frame/product/controller.dart
+39
-8
lib/pages/frame/product/view.dart
lib/pages/frame/product/view.dart
+8
-6
lib/pages/main/controller.dart
lib/pages/main/controller.dart
+6
-5
lib/pages/main/widgets/banner.dart
lib/pages/main/widgets/banner.dart
+11
-3
lib/pages/main/widgets/categories.dart
lib/pages/main/widgets/categories.dart
+9
-8
lib/pages/main/widgets/constants.dart
lib/pages/main/widgets/constants.dart
+28
-0
lib/pages/main/widgets/list.dart
lib/pages/main/widgets/list.dart
+25
-20
lib/pages/main/widgets/swiper.dart
lib/pages/main/widgets/swiper.dart
+3
-3
lib/pages/template/view.dart
lib/pages/template/view.dart
+64
-4
lib/pages/template/widgets/hello.dart
lib/pages/template/widgets/hello.dart
+164
-171
lib/pages/user/view.dart
lib/pages/user/view.dart
+15
-13
lib/pages1/chat/chat_page.dart
lib/pages1/chat/chat_page.dart
+1
-1
lib/pages1/home/home_page.dart
lib/pages1/home/home_page.dart
+1
-1
pubspec.lock
pubspec.lock
+14
-0
pubspec.yaml
pubspec.yaml
+2
-0
No files found.
ios/Podfile.lock
View file @
c7740f49
...
...
@@ -126,6 +126,8 @@ PODS:
- Toast (4.0.0)
- url_launcher_ios (0.0.1):
- Flutter
- vibration (1.7.5):
- Flutter
- video_player_avfoundation (0.0.1):
- Flutter
- webview_flutter_wkwebview (0.0.1):
...
...
@@ -152,6 +154,7 @@ DEPENDENCIES:
- smart_auth (from `.symlinks/plugins/smart_auth/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- vibration (from `.symlinks/plugins/vibration/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
...
...
@@ -214,6 +217,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
vibration:
:path: ".symlinks/plugins/vibration/ios"
video_player_avfoundation:
:path: ".symlinks/plugins/video_player_avfoundation/ios"
webview_flutter_wkwebview:
...
...
@@ -255,6 +260,7 @@ SPEC CHECKSUMS:
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
url_launcher_ios: fb12c43172927bb5cf75aeebd073f883801f1993
vibration: 7d883d141656a1c1a6d8d238616b2042a51a1241
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f
...
...
lib/common/apis/news.dart
View file @
c7740f49
...
...
@@ -24,6 +24,15 @@ class NewsAPI {
return
response
[
'data'
];
}
static
Future
<
String
>
sendMessageByDetailId
(
dynamic
params
,
String
detailId
)
async
{
var
response
=
await
HttpUtil
().
post
(
'/openAi/aiAnswer/
${detailId}
'
,
data:
params
);
return
response
[
'data'
];
}
// /api/openAi/aiAnswer/{detailId}
// /// 翻页
// /// refresh 是否刷新
// static Future<NewsPageListResponseEntity> newsPageList({
...
...
lib/common/entities/classFyDetail.dart
View file @
c7740f49
...
...
@@ -60,6 +60,7 @@ class ClassifyDetialEntity {
required
this
.
isShow
,
required
this
.
template
,
required
this
.
detailParamsEntityList
,
required
this
.
icon
,
});
final
int
id
;
...
...
@@ -67,6 +68,7 @@ class ClassifyDetialEntity {
final
String
detailDesc
;
final
int
isShow
;
final
String
template
;
final
String
icon
;
final
List
<
detailParamsEntity
>
detailParamsEntityList
;
factory
ClassifyDetialEntity
.
fromJson
(
String
str
)
=>
...
...
@@ -77,6 +79,7 @@ class ClassifyDetialEntity {
factory
ClassifyDetialEntity
.
fromMap
(
Map
<
String
,
dynamic
>
json
)
=>
ClassifyDetialEntity
(
id:
json
[
"id"
],
icon:
json
[
'icon'
],
detailName:
json
[
"detailName"
],
detailDesc:
json
[
"detailDesc"
],
template:
json
[
'template'
],
...
...
@@ -93,6 +96,7 @@ class ClassifyDetialEntity {
// detailParamsEntityList:json['detailParamsEntityList'];
Map
<
String
,
dynamic
>
toMap
()
=>
{
"id"
:
id
,
"icon"
:
icon
,
"detailName"
:
detailName
,
"detailDesc"
:
detailDesc
,
"isShow"
:
isShow
,
...
...
lib/common/store/user.dart
View file @
c7740f49
...
...
@@ -44,8 +44,8 @@ class UserStore extends GetxController {
handleLogin
(
LoginEntity
res
)
async
{
await
setToken
(
res
.
token
);
await
saveProfile
(
IntegralEntity
(
id:
res
.
id
,
username:
res
.
username
,
token:
res
.
token
)
);
IntegralEntity
userInfo
=
await
UserAPI
.
getUserIntegral
();
await
UserStore
.
to
.
getUserInfo
(
userInfo
);
_isLogin
.
value
=
true
;
Get
.
offAndToNamed
(
AppRoutes
.
Application
);
}
...
...
@@ -98,7 +98,7 @@ class UserStore extends GetxController {
// 注销
Future
<
void
>
onLogout
()
async
{
if
(
_isLogin
.
value
)
await
UserAPI
.
logout
();
//
if (_isLogin.value) await UserAPI.logout();
await
StorageService
.
to
.
remove
(
STORAGE_USER_TOKEN_KEY
);
_isLogin
.
value
=
false
;
token
=
''
;
...
...
lib/common/values/server.dart
View file @
c7740f49
// baidu yapi
// const SERVER_API_URL = 'https://yapi.baidu.com/mock/41008';
// const SERVER_API_URL = 'https://yapi.ducafecat.tech/mock/11';
const
SERVER_API_URL
=
'http://101.34.153.228:8083/api'
;
//
const SERVER_API_URL = 'http://101.34.153.228:8083/api';
const
SERVER_API_URL
=
'http://192.168.2.178:8083/api'
;
// AppRoutes.PRODUCT_PAGE
//http://192.168.2.178:8083/api/doc.html
// static const String baseUrl = 'http://101.34.153.228:8083'; // 基础接口地址
// static const String baseApiUrl = '${baseUrl}/api'; // 基础接口地址
...
...
lib/common/widgets/app.dart
View file @
c7740f49
...
...
@@ -10,7 +10,7 @@ AppBar transparentAppBar({
})
{
return
AppBar
(
backgroundColor:
Color
.
fromRGBO
(
41
,
45
,
62
,
1.00
),
elevation:
0
,
// elevation: 2
,
title:
title
,
leading:
leading
??
null
,
// actions: actions,
...
...
lib/entity/plan_entity.dart
View file @
c7740f49
...
...
@@ -141,12 +141,14 @@ class ClassifyEntity {
required
this
.
classifyName
,
required
this
.
classifyDesc
,
required
this
.
isShow
,
required
this
.
icon
,
});
final
int
id
;
final
String
classifyName
;
final
String
classifyDesc
;
final
int
isShow
;
final
String
icon
;
factory
ClassifyEntity
.
fromJson
(
String
str
)
=>
ClassifyEntity
.
fromMap
(
json
.
decode
(
str
));
...
...
@@ -157,12 +159,15 @@ class ClassifyEntity {
id:
json
[
"id"
],
classifyName:
json
[
"classifyName"
],
classifyDesc:
json
[
"classifyDesc"
],
icon:
json
[
'icon'
],
isShow:
json
[
'isShow'
]);
Map
<
String
,
dynamic
>
toMap
()
=>
{
"id"
:
id
,
"classifyName"
:
classifyName
,
"classifyDesc"
:
classifyDesc
,
"isShow"
:
isShow
"isShow"
:
isShow
,
"icon"
:
icon
,
};
}
...
...
lib/package/chat_dash/dash_chat_2.dart
0 → 100644
View file @
c7740f49
library
dash_chat_2
;
import
'dart:math'
;
import
'package:animated_text_kit/animated_text_kit.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_parsed_text/flutter_parsed_text.dart'
;
import
'package:gradient_borders/input_borders/gradient_outline_input_border.dart'
;
import
'package:intl/intl.dart'
as
intl
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:video_player/video_player.dart'
as
vp
;
import
'src/widgets/image_provider/image_provider.dart'
;
export
'package:flutter_parsed_text/flutter_parsed_text.dart'
;
part
'src/dash_chat.dart'
;
part
'src/models/chat_media.dart'
;
part
'src/models/chat_message.dart'
;
part
'src/models/chat_user.dart'
;
part
'src/models/cursor_style.dart'
;
part
'src/models/input_options.dart'
;
part
'src/models/mention.dart'
;
part
'src/models/message_list_options.dart'
;
part
'src/models/message_options.dart'
;
part
'src/models/quick_reply.dart'
;
part
'src/models/quick_reply_options.dart'
;
part
'src/models/scroll_to_bottom_options.dart'
;
part
'src/widgets/input_toolbar/default_input_decoration.dart'
;
part
'src/widgets/input_toolbar/default_send_button.dart'
;
part
'src/widgets/input_toolbar/input_toolbar.dart'
;
part
'src/widgets/message_list/default_date_separator.dart'
;
part
'src/widgets/message_list/default_scroll_to_bottom.dart'
;
part
'src/widgets/message_list/message_list.dart'
;
part
'src/widgets/message_row/default_avatar.dart'
;
part
'src/widgets/message_row/default_message_decoration.dart'
;
part
'src/widgets/message_row/default_message_text.dart'
;
part
'src/widgets/message_row/default_parse_patterns.dart'
;
part
'src/widgets/message_row/default_user_name.dart'
;
part
'src/widgets/message_row/media_container.dart'
;
part
'src/widgets/message_row/message_row.dart'
;
part
'src/widgets/message_row/text_container.dart'
;
part
'src/widgets/message_row/video_player.dart'
;
part
'src/widgets/quick_replies/default_quick_reply.dart'
;
part
'src/widgets/quick_replies/quick_replies.dart'
;
part
'src/widgets/typing_users/default_typing_builder.dart'
;
part
'src/widgets/typing_users/typing_indicator.dart'
;
lib/package/chat_dash/src/dash_chat.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Entry point}
class
DashChat
extends
StatelessWidget
{
const
DashChat
({
required
this
.
currentUser
,
required
this
.
onSend
,
required
this
.
messages
,
this
.
inputOptions
=
const
InputOptions
(),
this
.
messageOptions
=
const
MessageOptions
(),
this
.
messageListOptions
=
const
MessageListOptions
(),
this
.
quickReplyOptions
=
const
QuickReplyOptions
(),
this
.
scrollToBottomOptions
=
const
ScrollToBottomOptions
(),
this
.
readOnly
=
false
,
this
.
typingUsers
,
Key
?
key
,
})
:
super
(
key:
key
);
/// The current user of the chat
final
ChatUser
currentUser
;
/// Function to call when the user sends a message
final
void
Function
(
ChatMessage
message
)
onSend
;
/// List of messages visible in the chat
final
List
<
ChatMessage
>
messages
;
/// Options to customize the behaviour and design of the chat input
final
InputOptions
inputOptions
;
/// Options to customize the behaviour and design of the messages
final
MessageOptions
messageOptions
;
/// Options to customize the behaviour and design of the overall list of message
final
MessageListOptions
messageListOptions
;
/// Options to customize the behaviour and design of the quick replies
final
QuickReplyOptions
quickReplyOptions
;
/// Options to customize the behaviour and design of the scroll-to-bottom button
final
ScrollToBottomOptions
scrollToBottomOptions
;
/// Option to make the chat read only, it will hide the input field
final
bool
readOnly
;
/// List of users currently typing in the chat
final
List
<
ChatUser
>?
typingUsers
;
@override
Widget
build
(
BuildContext
context
)
{
return
Column
(
children:
<
Widget
>[
Expanded
(
child:
MessageList
(
currentUser:
currentUser
,
messages:
messages
,
messageOptions:
messageOptions
,
messageListOptions:
messageListOptions
,
quickReplyOptions:
quickReplyOptions
,
scrollToBottomOptions:
scrollToBottomOptions
,
typingUsers:
typingUsers
,
),
),
if
(!
readOnly
)
InputToolbar
(
inputOptions:
inputOptions
,
currentUser:
currentUser
,
onSend:
onSend
,
),
],
);
}
}
lib/package/chat_dash/src/models/chat_media.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Models}
class
ChatMedia
{
ChatMedia
({
required
this
.
url
,
required
this
.
fileName
,
required
this
.
type
,
this
.
isUploading
=
false
,
this
.
uploadedDate
,
this
.
customProperties
,
});
/// Create a ChatMedia instance from json data
factory
ChatMedia
.
fromJson
(
Map
<
String
,
dynamic
>
jsonData
)
{
return
ChatMedia
(
url:
jsonData
[
'url'
].
toString
(),
fileName:
jsonData
[
'fileName'
].
toString
(),
type:
MediaType
.
parse
(
jsonData
[
'type'
].
toString
()),
isUploading:
jsonData
[
'isUploading'
]
==
true
,
uploadedDate:
jsonData
[
'uploadedDate'
]
!=
null
?
DateTime
.
parse
(
jsonData
[
'uploadedDate'
].
toString
()).
toLocal
()
:
null
,
customProperties:
jsonData
[
'customProperties'
]
as
Map
<
String
,
dynamic
>,
);
}
/// URL of the media, can local (will use FileImage) or remote (will use NetworkImage)
String
url
;
/// Name of the file that will be shown in some cases
String
fileName
;
/// Type of media
MediaType
type
;
/// If the media is still uploading, usefull to add a visual feedback
bool
isUploading
;
/// Uploaded date of the media
DateTime
?
uploadedDate
;
/// A list of custom properties to extend the existing ones
/// in case you need to store more things.
/// Can be useful to extend existing features
Map
<
String
,
dynamic
>?
customProperties
;
/// Convert a ChatMedia into a json
Map
<
String
,
dynamic
>
toJson
()
{
return
<
String
,
dynamic
>{
'url'
:
url
,
'type'
:
type
.
toString
(),
'fileName'
:
fileName
,
'isUploading'
:
isUploading
,
'uploadedDate'
:
uploadedDate
?.
toUtc
().
toIso8601String
(),
'customProperties'
:
customProperties
,
};
}
}
class
MediaType
{
const
MediaType
.
_internal
(
this
.
_value
);
final
String
_value
;
@override
String
toString
()
=>
_value
;
static
MediaType
parse
(
String
value
)
{
switch
(
value
)
{
case
'image'
:
return
MediaType
.
image
;
case
'video'
:
return
MediaType
.
video
;
case
'file'
:
return
MediaType
.
file
;
default
:
throw
UnsupportedError
(
'
$value
is not a valid MediaType'
);
}
}
static
const
MediaType
image
=
MediaType
.
_internal
(
'image'
);
static
const
MediaType
video
=
MediaType
.
_internal
(
'video'
);
static
const
MediaType
file
=
MediaType
.
_internal
(
'file'
);
}
lib/package/chat_dash/src/models/chat_message.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Models}
class
ChatMessage
{
ChatMessage
({
required
this
.
user
,
required
this
.
createdAt
,
this
.
text
=
''
,
this
.
medias
,
this
.
quickReplies
,
this
.
customProperties
,
this
.
mentions
,
this
.
status
=
MessageStatus
.
none
,
this
.
replyTo
,
});
/// Create a ChatMessage instance from json data
factory
ChatMessage
.
fromJson
(
Map
<
String
,
dynamic
>
jsonData
)
{
return
ChatMessage
(
user:
ChatUser
.
fromJson
(
jsonData
[
'user'
]
as
Map
<
String
,
dynamic
>),
createdAt:
DateTime
.
parse
(
jsonData
[
'createdAt'
].
toString
()).
toLocal
(),
text:
jsonData
[
'text'
]?.
toString
()
??
''
,
medias:
jsonData
[
'medias'
]
!=
null
?
(
jsonData
[
'medias'
]
as
List
<
dynamic
>)
.
map
((
dynamic
media
)
=>
ChatMedia
.
fromJson
(
media
as
Map
<
String
,
dynamic
>))
.
toList
()
:
<
ChatMedia
>[],
quickReplies:
jsonData
[
'quickReplies'
]
!=
null
?
(
jsonData
[
'quickReplies'
]
as
List
<
dynamic
>)
.
map
((
dynamic
quickReply
)
=>
QuickReply
.
fromJson
(
quickReply
as
Map
<
String
,
dynamic
>))
.
toList
()
:
<
QuickReply
>[],
customProperties:
jsonData
[
'customProperties'
]
as
Map
<
String
,
dynamic
>,
mentions:
jsonData
[
'mentions'
]
!=
null
?
(
jsonData
[
'mentions'
]
as
List
<
dynamic
>)
.
map
((
dynamic
mention
)
=>
Mention
.
fromJson
(
mention
as
Map
<
String
,
dynamic
>))
.
toList
()
:
<
Mention
>[],
status:
MessageStatus
.
parse
(
jsonData
[
'status'
].
toString
()),
replyTo:
jsonData
[
'replyTo'
]
!=
null
?
ChatMessage
.
fromJson
(
jsonData
[
'replyTo'
]
as
Map
<
String
,
dynamic
>)
:
null
,
);
}
/// Text of the message (optional because you can also just send a media)
String
text
;
/// Author of the message
ChatUser
user
;
/// List of medias of the message
List
<
ChatMedia
>?
medias
;
/// A list of quick replies that users can use to reply to this message
List
<
QuickReply
>?
quickReplies
;
/// A list of custom properties to extend the existing ones
/// in case you need to store more things.
/// Can be useful to extend existing features
Map
<
String
,
dynamic
>?
customProperties
;
/// Date of the message
DateTime
createdAt
;
/// Mentionned elements in the message
List
<
Mention
>?
mentions
;
/// Status of the message TODO:
MessageStatus
?
status
;
/// If the message is a reply of another one TODO:
ChatMessage
?
replyTo
;
/// Convert a ChatMessage into a json
Map
<
String
,
dynamic
>
toJson
()
{
return
<
String
,
dynamic
>{
'user'
:
user
.
toJson
(),
'createdAt'
:
createdAt
.
toUtc
().
toIso8601String
(),
'text'
:
text
,
'medias'
:
medias
?.
map
((
ChatMedia
media
)
=>
media
.
toJson
()).
toList
(),
'quickReplies'
:
quickReplies
?.
map
((
QuickReply
quickReply
)
=>
quickReply
.
toJson
())
.
toList
(),
'customProperties'
:
customProperties
,
'mentions'
:
mentions
,
'status'
:
status
.
toString
(),
'replyTo'
:
replyTo
?.
toJson
(),
};
}
}
class
MessageStatus
{
const
MessageStatus
.
_internal
(
this
.
_value
);
final
String
_value
;
@override
String
toString
()
=>
_value
;
static
MessageStatus
parse
(
String
value
)
{
switch
(
value
)
{
case
'none'
:
return
MessageStatus
.
none
;
case
'read'
:
return
MessageStatus
.
read
;
case
'received'
:
return
MessageStatus
.
received
;
case
'pending'
:
return
MessageStatus
.
pending
;
default
:
return
MessageStatus
.
none
;
}
}
static
const
MessageStatus
none
=
MessageStatus
.
_internal
(
'none'
);
static
const
MessageStatus
read
=
MessageStatus
.
_internal
(
'read'
);
static
const
MessageStatus
received
=
MessageStatus
.
_internal
(
'received'
);
static
const
MessageStatus
pending
=
MessageStatus
.
_internal
(
'pending'
);
}
lib/package/chat_dash/src/models/chat_user.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Models}
class
ChatUser
{
ChatUser
({
required
this
.
id
,
this
.
profileImage
,
this
.
customProperties
,
this
.
firstName
,
this
.
lastName
,
});
/// Create a ChatUser instance from json data
factory
ChatUser
.
fromJson
(
Map
<
String
,
dynamic
>
jsonData
)
{
return
ChatUser
(
id:
jsonData
[
'id'
].
toString
(),
profileImage:
jsonData
[
'profileImage'
]?.
toString
(),
firstName:
jsonData
[
'firstName'
]?.
toString
(),
lastName:
jsonData
[
'lastName'
]?.
toString
(),
customProperties:
jsonData
[
'customProperties'
]
as
Map
<
String
,
dynamic
>,
);
}
/// Id of the user
String
id
;
/// Profile image of the user
String
?
profileImage
;
/// A list of custom properties to extend the existing ones
/// in case you need to store more things.
/// Can be useful to extend existing features
Map
<
String
,
dynamic
>?
customProperties
;
/// First name of the user,
/// if you only have the name as one string
/// you can put the entire value in the [fristName] field
String
?
firstName
;
/// Last name of the user
String
?
lastName
;
/// Get the full name (firstName + lastName) of the user
String
getFullName
()
{
return
(
firstName
??
''
)
+
(
firstName
!=
null
&&
lastName
!=
null
?
' '
+
lastName
!
:
lastName
??
''
);
}
/// Convert a ChatUser into a json
Map
<
String
,
dynamic
>
toJson
()
{
return
<
String
,
dynamic
>{
'id'
:
id
,
'profileImage'
:
profileImage
,
'firstName'
:
firstName
,
'lastName'
:
lastName
,
'customProperties'
:
customProperties
,
};
}
}
lib/package/chat_dash/src/models/cursor_style.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Customization}
class
CursorStyle
{
const
CursorStyle
({
this
.
color
,
this
.
hide
=
false
,
this
.
width
=
2.0
,
});
/// Color of the cursor
final
Color
?
color
;
/// Hide or not the cursor
final
bool
hide
;
/// Width of the cursor
final
double
width
;
}
lib/package/chat_dash/src/models/input_options.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Customization}
class
InputOptions
{
const
InputOptions
({
this
.
textController
,
this
.
focusNode
,
this
.
inputTextDirection
=
TextDirection
.
ltr
,
this
.
onMention
,
this
.
onMentionTriggers
=
const
<
String
>[
'@'
],
this
.
onTextChange
,
this
.
inputDisabled
=
false
,
this
.
inputDecoration
,
this
.
textCapitalization
=
TextCapitalization
.
none
,
this
.
alwaysShowSend
=
false
,
this
.
sendOnEnter
=
false
,
this
.
textInputAction
,
this
.
maxInputLength
,
this
.
leading
,
this
.
trailing
,
this
.
sendButtonBuilder
,
this
.
inputTextStyle
,
this
.
inputToolbarStyle
,
this
.
inputMaxLines
=
5
,
this
.
showTraillingBeforeSend
=
false
,
this
.
inputToolbarPadding
=
const
EdgeInsets
.
all
(
8.0
),
this
.
inputToolbarMargin
=
const
EdgeInsets
.
only
(
top:
8.0
),
this
.
cursorStyle
=
const
CursorStyle
(),
this
.
autocorrect
=
true
,
});
/// Function to call when a mention is triggered in the input,
/// ie: typing ' @'
/// You need to return a list of widget that will be shown inside the selection overlay,
/// for instance user ListTiles
final
Future
<
List
<
Widget
>>
Function
(
String
trigger
,
String
value
,
void
Function
(
String
value
)
onMentionClick
)?
onMention
;
/// The list of string triggers for the onMention callback
/// By default it only includes '@' character
final
List
<
String
>
onMentionTriggers
;
/// Function to call when the input text changee
final
void
Function
(
String
value
)?
onTextChange
;
/// Always show the send button, will be hidden when the text is empty otherwise
final
bool
alwaysShowSend
;
/// Send the message when the user presses the enter key
final
bool
sendOnEnter
;
/// Builder to create your own send button widget
/// You can use defaultSendButton to only override some variables
final
Widget
Function
(
void
Function
()
send
)?
sendButtonBuilder
;
/// Text controller for the input field
final
TextEditingController
?
textController
;
/// Focus node of the input field
final
FocusNode
?
focusNode
;
/// Use to change the direction of the text
final
TextDirection
inputTextDirection
;
/// To make the input disabled
final
bool
inputDisabled
;
/// Input decoration to customize the design of the input
/// You can use defaultInputDecoration to only orride some variables
final
InputDecoration
?
inputDecoration
;
/// Use to override the default TextCapitalization
final
TextCapitalization
textCapitalization
;
/// An action the user has requested the text input control to perform
final
TextInputAction
?
textInputAction
;
/// If you want to limit the length of the text
final
int
?
maxInputLength
;
/// A list of widget to show before the input
final
List
<
Widget
>?
leading
;
/// A list of widget to show after the input
final
List
<
Widget
>?
trailing
;
/// To customize the text style of the inpu
final
TextStyle
?
inputTextStyle
;
/// To customize the overall container of the input
final
BoxDecoration
?
inputToolbarStyle
;
/// Max number of visible lines of the input, it will grow until this value and then scroll
final
int
inputMaxLines
;
/// If [trailing] should be shown before or after the send button
final
bool
showTraillingBeforeSend
;
/// Padding of the overall container of the input
final
EdgeInsets
?
inputToolbarPadding
;
/// Margin of the overall container of the input
final
EdgeInsets
?
inputToolbarMargin
;
/// Style of the cursor
final
CursorStyle
cursorStyle
;
/// Whether to enable autocorrection. Defaults to true.
final
bool
autocorrect
;
}
lib/package/chat_dash/src/models/mention.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Models}
class
Mention
{
Mention
({
required
this
.
title
,
this
.
customProperties
,
});
/// Create a Mention instance from json data
factory
Mention
.
fromJson
(
Map
<
String
,
dynamic
>
jsonData
)
{
return
Mention
(
title:
jsonData
[
'title'
].
toString
(),
customProperties:
jsonData
[
'customProperties'
]
as
Map
<
String
,
dynamic
>,
);
}
/// Title of the mention,
/// it's what is visible in the message: @userName
String
title
;
/// A list of custom properties to save any data you might need
/// For instance a user Id
Map
<
String
,
dynamic
>?
customProperties
;
/// Convert a Mention into a json
Map
<
String
,
dynamic
>
toJson
()
{
return
<
String
,
dynamic
>{
'title'
:
title
,
'customProperties'
:
customProperties
,
};
}
}
lib/package/chat_dash/src/models/message_list_options.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Customization}
class
MessageListOptions
{
const
MessageListOptions
({
this
.
showDateSeparator
=
true
,
this
.
dateSeparatorFormat
,
this
.
dateSeparatorBuilder
,
this
.
separatorFrequency
=
SeparatorFrequency
.
days
,
this
.
scrollController
,
this
.
chatFooterBuilder
,
this
.
showFooterBeforeQuickReplies
=
false
,
this
.
loadEarlierBuilder
,
this
.
onLoadEarlier
,
this
.
typingBuilder
,
this
.
scrollPhysics
,
});
/// If you want to who a date separator between messages of different dates
final
bool
showDateSeparator
;
/// The formating of the date in the date separator.
/// By default it will adapt according to the difference with today
final
intl
.
DateFormat
?
dateSeparatorFormat
;
/// If you want to create you own separator widget
/// You can use DefaultDateSeparator to only override some variables
final
Widget
Function
(
DateTime
date
)?
dateSeparatorBuilder
;
/// The frequency of the separator
final
SeparatorFrequency
separatorFrequency
;
/// Scroll controller of the list of message
final
ScrollController
?
scrollController
;
/// A widget to show at the bottom of the chat
/// (between the input and the chat content)
final
Widget
?
chatFooterBuilder
;
/// If you wnat to show [chatFooterBuilder] before or after the quick replies
final
bool
showFooterBeforeQuickReplies
;
/// If you want to show a widget when the top of the list is reached
final
Widget
?
loadEarlierBuilder
;
/// Function to call when the top of the list is reached
/// Usefull to load more messages
final
Future
<
void
>
Function
()?
onLoadEarlier
;
/// Builder to create your own typing widget
final
Widget
Function
(
ChatUser
user
)?
typingBuilder
;
/// Scroll physics of the ListView
final
ScrollPhysics
?
scrollPhysics
;
}
enum
SeparatorFrequency
{
days
,
hours
}
lib/package/chat_dash/src/models/message_options.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Customization}
class
MessageOptions
{
const
MessageOptions
({
this
.
showCurrentUserAvatar
=
false
,
this
.
showOtherUsersAvatar
=
true
,
this
.
showOtherUsersName
=
true
,
this
.
userNameBuilder
,
this
.
avatarBuilder
,
this
.
onPressAvatar
,
this
.
onLongPressAvatar
,
this
.
onLongPressMessage
,
this
.
onPressMessage
,
this
.
onPressMention
,
this
.
currentUserContainerColor
,
this
.
currentUserTextColor
,
this
.
containerColor
,
this
.
textColor
,
this
.
messagePadding
,
this
.
maxWidth
,
this
.
messageDecorationBuilder
,
this
.
top
,
this
.
bottom
,
this
.
messageRowBuilder
,
this
.
messageTextBuilder
,
this
.
parsePatterns
,
this
.
textBeforeMedia
=
true
,
this
.
onTapMedia
,
this
.
showTime
=
false
,
this
.
timeFormat
,
this
.
messageTimeBuilder
,
this
.
messageMediaBuilder
,
});
/// Format of the time if [showTime] is true
/// Default to: DateFormat('HH:mm')
final
intl
.
DateFormat
?
timeFormat
;
/// If you want to show the time under the text of each message
final
bool
showTime
;
/// If you want to show the avatar of the current user
final
bool
showCurrentUserAvatar
;
/// If you want to show the avatar of the other users
final
bool
showOtherUsersAvatar
;
/// If you want to show the name of the other users above the messages
/// Usefull in group chats
final
bool
showOtherUsersName
;
/// If you want to create your own userName widget when [showOtherUsersName] is true
/// You can use DefaultUserName to only override some variables
final
Widget
Function
(
ChatUser
user
)?
userNameBuilder
;
/// Builder to create your own avatar
/// You can use DefaultAvatar to only override some varibales
final
Widget
Function
(
ChatUser
,
Function
?
onPressAvatar
,
Function
?
onLongPressAvatar
)?
avatarBuilder
;
/// Function to call when the user press on an avatar
final
Function
(
ChatUser
)?
onPressAvatar
;
/// Function to call when the user long press on an avatar
final
Function
(
ChatUser
)?
onLongPressAvatar
;
/// Function to call when the user long press on a message
final
Function
(
ChatMessage
)?
onLongPressMessage
;
/// Function to call when the user press on a message
final
Function
(
ChatMessage
)?
onPressMessage
;
/// Function to call when the user press on a message mention
final
Function
(
Mention
)?
onPressMention
;
/// Color of the current user chat bubbles
/// Default to primary color
final
Color
?
currentUserContainerColor
;
/// Color of the current user text in chat bubbles
/// Default to white
final
Color
?
currentUserTextColor
;
/// Color of the other users chat bubbles
/// Default to Colors.grey[100]
final
Color
?
containerColor
;
/// Color of the other users text in chat bubbles
/// Default to black
final
Color
?
textColor
;
/// Builder to create the entire message row yourself
final
Widget
Function
(
ChatMessage
message
,
ChatMessage
?
previousMessage
,
ChatMessage
?
nextMessage
,
bool
isAfterDateSeparator
,
bool
isBeforeDateSeparator
,
)?
messageRowBuilder
;
/// Builder to create own message text widget
final
Widget
Function
(
ChatMessage
message
,
ChatMessage
?
previousMessage
,
ChatMessage
?
nextMessage
)?
messageTextBuilder
;
/// Builder to create your own media container widget
final
Widget
Function
(
ChatMessage
message
,
ChatMessage
?
previousMessage
,
ChatMessage
?
nextMessage
)?
messageMediaBuilder
;
/// Builder to create your own time widget
/// (shown under the text when [showTime] is true)
final
Widget
Function
(
ChatMessage
message
,
bool
isOwnMessage
)?
messageTimeBuilder
;
/// List of MatchText using flutter_parsed_text library
/// to parse and customize accordingly some part of the text
/// By default ParsedType.URL is set and will use launchUrl to open the link
final
List
<
MatchText
>?
parsePatterns
;
/// Padding arround the message
/// Default to: EdgeInsets.all(11)
final
EdgeInsets
?
messagePadding
;
/// Max message width
/// Default to: null, MediaQuery.of(context).size.width * 0.7
final
double
?
maxWidth
;
/// When a message have both an text and a list of media
/// it will determine which one th show first
final
bool
textBeforeMedia
;
/// To create your own BoxDecoration fot the chat bubble
/// You can use defaultMessageDecoration to only override some variables
final
BoxDecoration
Function
(
ChatMessage
message
,
ChatMessage
?
previousMessage
,
ChatMessage
?
nextMessage
)?
messageDecorationBuilder
;
/// A widget to show above the chat bubble
final
Widget
Function
(
ChatMessage
message
,
ChatMessage
?
previousMessage
,
ChatMessage
?
nextMessage
)?
top
;
/// A widget to show under the chat bubble
final
Widget
Function
(
ChatMessage
message
,
ChatMessage
?
previousMessage
,
ChatMessage
?
nextMessage
)?
bottom
;
/// Function to call when the user clicks on a media
/// Will not work with the default video player
final
void
Function
(
ChatMedia
media
)?
onTapMedia
;
}
lib/package/chat_dash/src/models/quick_reply.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Models}
class
QuickReply
{
QuickReply
({
required
this
.
title
,
this
.
value
,
this
.
customProperties
,
});
/// Create a QuickReply instance from json data
factory
QuickReply
.
fromJson
(
Map
<
String
,
dynamic
>
jsonData
)
{
return
QuickReply
(
title:
jsonData
[
'title'
].
toString
(),
value:
jsonData
[
'value'
]?.
toString
(),
customProperties:
jsonData
[
'customProperties'
]
as
Map
<
String
,
dynamic
>,
);
}
/// Title of the quick reply,
/// it's what will be visible in the quick replies list
String
title
;
/// Actual value of the quick reply
/// Use that if you want to have a message text different from the title
String
?
value
;
/// A list of custom properties to extend the existing ones
/// in case you need to store more things.
/// Can be useful to extend existing features
Map
<
String
,
dynamic
>?
customProperties
;
/// Convert a QuickReply into a json
Map
<
String
,
dynamic
>
toJson
()
{
return
<
String
,
dynamic
>{
'title'
:
title
,
'value'
:
value
,
'customProperties'
:
customProperties
,
};
}
}
lib/package/chat_dash/src/models/quick_reply_options.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Customization}
class
QuickReplyOptions
{
const
QuickReplyOptions
({
this
.
onTapQuickReply
,
this
.
quickReplyPadding
,
this
.
quickReplyMargin
,
this
.
quickReplyStyle
,
this
.
quickReplyTextStyle
,
this
.
quickReplyBuilder
,
});
/// Function to call when the user click on a quick reply
/// Use that to create a message and send it
final
Function
(
QuickReply
)?
onTapQuickReply
;
/// Padding of a quick reply container
final
EdgeInsets
?
quickReplyPadding
;
/// Margin of a quick reply container
final
EdgeInsets
?
quickReplyMargin
;
/// BoxDecoration of a quick reply container
final
BoxDecoration
?
quickReplyStyle
;
/// TextStyle of a quick reply
final
TextStyle
?
quickReplyTextStyle
;
/// Builder to create your own quickReply builder
final
Widget
Function
(
QuickReply
)?
quickReplyBuilder
;
}
lib/package/chat_dash/src/models/scroll_to_bottom_options.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Customization}
class
ScrollToBottomOptions
{
const
ScrollToBottomOptions
({
this
.
disabled
=
false
,
this
.
scrollToBottomBuilder
,
this
.
onScrollToBottomPress
,
});
/// If you don't want to show the scroll-to-bottom widget
final
bool
disabled
;
/// Builder to create your own scroll-to-bottom widget
/// You can use DefaultScrollToBottom to only override some variables
final
Widget
Function
(
ScrollController
scrollController
)?
scrollToBottomBuilder
;
/// Function to call when the scroll-to-bottom widget is pressed
/// It will scroll down in any case
final
void
Function
()?
onScrollToBottomPress
;
}
lib/package/chat_dash/src/widgets/image_provider/image_provider.dart
0 → 100644
View file @
c7740f49
export
'image_provider_mobile.dart'
if
(
dart
.
library
.
html
)
'image_provider_web.dart'
;
lib/package/chat_dash/src/widgets/image_provider/image_provider_mobile.dart
0 → 100644
View file @
c7740f49
import
'dart:io'
;
import
'package:cached_network_image/cached_network_image.dart'
;
import
'package:flutter/material.dart'
;
ImageProvider
getImageProvider
(
String
url
)
{
if
(
url
.
startsWith
(
'http'
))
{
return
CachedNetworkImageProvider
(
url
);
}
else
if
(
url
.
startsWith
(
'assets'
))
{
return
AssetImage
(
url
);
}
else
{
return
FileImage
(
File
(
url
),
);
}
}
lib/package/chat_dash/src/widgets/image_provider/image_provider_web.dart
0 → 100644
View file @
c7740f49
import
'package:flutter/material.dart'
;
ImageProvider
getImageProvider
(
String
url
)
{
if
(
url
.
startsWith
(
'http'
))
{
return
NetworkImage
(
url
);
}
else
{
return
const
AssetImage
(
'assets/placeholder.png'
,
package:
'dash_chat_2'
,
);
}
}
lib/package/chat_dash/src/widgets/input_toolbar/default_input_decoration.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
// 'package:gradient_borders/gradient_borders.dart';
/// {@category Default widgets}
InputDecoration
defaultInputDecoration
(
void
Function
()
sendMessage
,
{
String
hintText
=
'请输入问题...'
,
TextStyle
hintStyle
=
const
TextStyle
(
color:
Colors
.
grey
),
Color
?
fillColor
,
})
=>
InputDecoration
(
isDense:
true
,
hintText:
hintText
,
hintStyle:
hintStyle
,
filled:
true
,
// fillColor: fillColor ?? Colors.grey[100],
contentPadding:
const
EdgeInsets
.
only
(
left:
18
,
top:
15
,
bottom:
15
,
),
suffixIcon:
IconButton
(
onPressed:
sendMessage
,
icon:
Icon
(
Icons
.
send
,
size:
30
,
),
// rgba(123, 238, 251, 1.00)
// rgba(122, 239, 251, 1.00)
color:
Color
.
fromRGBO
(
123
,
238
,
251
,
1
),
),
// Icon(Icons.abc_rounded),
// border: const InputBorder()
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(10),
// borderSide: const BorderSide(
// width: 10,
// style: BorderStyle.solid,
// ),
// ),
// rgba(116, 112, 249, 1.00)
enabledBorder:
GradientOutlineInputBorder
(
// rgba(140, 197, 208, 1.00)
borderRadius:
BorderRadius
.
circular
(
10
),
gradient:
LinearGradient
(
colors:
[
Color
.
fromRGBO
(
116
,
112
,
249
,
1.00
),
Color
.
fromRGBO
(
149
,
197
,
208
,
1.00
)
]),
width:
5
,
),
// OutlineInputBorder(
// borderRadius:
// BorderRadius.circular(10),
// borderSide: const BorderSide(
// width: 5,
// style: BorderStyle.solid,
// ),
// ),
focusedBorder:
GradientOutlineInputBorder
(
// rgba(140, 197, 208, 1.00)
borderRadius:
BorderRadius
.
circular
(
10
),
gradient:
LinearGradient
(
colors:
[
Color
.
fromRGBO
(
116
,
112
,
249
,
1.00
),
Color
.
fromRGBO
(
149
,
197
,
208
,
1.00
)
]),
width:
5
,
),
// focusedBorder: OutlineInputBorder(
// borderRadius: BorderRadius.circular(10),
// borderSide: const BorderSide(
// width: 5,
// style: BorderStyle.solid,
// ),
// ),
);
lib/package/chat_dash/src/widgets/input_toolbar/default_send_button.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
Widget
Function
(
Function
send
)
defaultSendButton
({
required
Color
color
,
IconData
icon
=
Icons
.
send
,
EdgeInsets
?
padding
,
})
=>
(
Function
fct
)
=>
InkWell
(
onTap:
()
=>
fct
(),
child:
Padding
(
padding:
padding
??
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
10
),
child:
Icon
(
Icons
.
send
,
color:
color
,
),
),
);
lib/package/chat_dash/src/widgets/input_toolbar/input_toolbar.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
InputToolbar
extends
StatefulWidget
{
const
InputToolbar
({
required
this
.
currentUser
,
required
this
.
onSend
,
this
.
inputOptions
=
const
InputOptions
(),
Key
?
key
,
})
:
super
(
key:
key
);
/// Options to custom the toolbar
final
InputOptions
inputOptions
;
/// Function to call when the message is sent (click on the send button)
final
Function
(
ChatMessage
)
onSend
;
/// Current user using the chat
final
ChatUser
currentUser
;
@override
_InputToolbarState
createState
()
=>
_InputToolbarState
();
}
class
_InputToolbarState
extends
State
<
InputToolbar
>
with
WidgetsBindingObserver
{
late
TextEditingController
textController
;
OverlayEntry
?
_overlayEntry
;
int
currentMentionIndex
=
-
1
;
String
currentTrigger
=
''
;
late
FocusNode
focusNode
;
@override
void
initState
()
{
textController
=
widget
.
inputOptions
.
textController
??
TextEditingController
();
focusNode
=
widget
.
inputOptions
.
focusNode
??
FocusNode
();
focusNode
.
addListener
(()
{
if
(!
focusNode
.
hasFocus
)
{
_clearOverlay
();
}
});
WidgetsBinding
.
instance
.
addObserver
(
this
);
super
.
initState
();
}
@override
void
didChangeMetrics
()
{
final
double
bottomInset
=
WidgetsBinding
.
instance
.
window
.
viewInsets
.
bottom
;
final
bool
isKeyboardActive
=
bottomInset
>
0.0
;
if
(!
isKeyboardActive
)
{
_clearOverlay
();
}
}
@override
void
dispose
()
{
WidgetsBinding
.
instance
.
removeObserver
(
this
);
_clearOverlay
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
padding:
widget
.
inputOptions
.
inputToolbarPadding
,
margin:
widget
.
inputOptions
.
inputToolbarMargin
,
decoration:
widget
.
inputOptions
.
inputToolbarStyle
,
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
<
Widget
>[
if
(
widget
.
inputOptions
.
leading
!=
null
)
...
widget
.
inputOptions
.
leading
!,
Expanded
(
child:
Directionality
(
textDirection:
widget
.
inputOptions
.
inputTextDirection
,
child:
TextField
(
focusNode:
focusNode
,
controller:
textController
,
enabled:
!
widget
.
inputOptions
.
inputDisabled
,
textCapitalization:
widget
.
inputOptions
.
textCapitalization
,
textInputAction:
widget
.
inputOptions
.
textInputAction
,
decoration:
widget
.
inputOptions
.
inputDecoration
??
defaultInputDecoration
(
_sendMessage
),
maxLength:
widget
.
inputOptions
.
maxInputLength
,
minLines:
1
,
maxLines:
widget
.
inputOptions
.
sendOnEnter
?
1
:
widget
.
inputOptions
.
inputMaxLines
,
cursorColor:
widget
.
inputOptions
.
cursorStyle
.
color
,
cursorWidth:
widget
.
inputOptions
.
cursorStyle
.
width
,
showCursor:
!
widget
.
inputOptions
.
cursorStyle
.
hide
,
style:
widget
.
inputOptions
.
inputTextStyle
,
onSubmitted:
(
String
value
)
{
if
(
widget
.
inputOptions
.
sendOnEnter
)
{
_sendMessage
();
}
},
onChanged:
(
String
value
)
async
{
setState
(()
{});
if
(
widget
.
inputOptions
.
onTextChange
!=
null
)
{
widget
.
inputOptions
.
onTextChange
!(
value
);
}
WidgetsBinding
.
instance
.
addPostFrameCallback
((
_
)
async
{
if
(
widget
.
inputOptions
.
onMention
!=
null
)
{
await
_checkMentions
(
value
);
}
});
},
autocorrect:
widget
.
inputOptions
.
autocorrect
,
),
),
),
if
(
widget
.
inputOptions
.
trailing
!=
null
&&
widget
.
inputOptions
.
showTraillingBeforeSend
)
...
widget
.
inputOptions
.
trailing
!,
//发送按钮重写
// if (widget.inputOptions.alwaysShowSend ||
// textController.text.isNotEmpty)
// widget.inputOptions.sendButtonBuilder != null
// ? widget.inputOptions.sendButtonBuilder!(_sendMessage)
// : defaultSendButton(color: Theme.of(context).primaryColor)(
// _sendMessage,
// ),
if
(
widget
.
inputOptions
.
trailing
!=
null
&&
!
widget
.
inputOptions
.
showTraillingBeforeSend
)
...
widget
.
inputOptions
.
trailing
!,
],
),
);
}
Future
<
void
>
_checkMentions
(
String
text
)
async
{
bool
hasMatch
=
false
;
for
(
final
String
trigger
in
widget
.
inputOptions
.
onMentionTriggers
)
{
final
RegExp
regexp
=
RegExp
(
r'(?<![^\s<>])'
+
trigger
+
r'([^\s<>]+)$'
);
if
(
regexp
.
hasMatch
(
text
))
{
hasMatch
=
true
;
currentMentionIndex
=
textController
.
text
.
indexOf
(
regexp
);
currentTrigger
=
trigger
;
List
<
Widget
>
children
=
await
widget
.
inputOptions
.
onMention
!(
trigger
,
regexp
.
firstMatch
(
text
)!.
group
(
1
)!,
_onMentionClick
,
);
_showMentionModal
(
children
);
}
}
if
(!
hasMatch
)
{
_clearOverlay
();
}
}
void
_onMentionClick
(
String
value
)
{
textController
.
text
=
textController
.
text
.
replaceRange
(
currentMentionIndex
,
textController
.
text
.
length
,
currentTrigger
+
value
,
);
textController
.
selection
=
TextSelection
.
collapsed
(
offset:
textController
.
text
.
length
,
);
_clearOverlay
();
}
void
_clearOverlay
()
{
if
(
_overlayEntry
!=
null
&&
_overlayEntry
!.
mounted
)
{
_overlayEntry
?.
remove
();
_overlayEntry
?.
dispose
();
}
}
void
_showMentionModal
(
List
<
Widget
>
children
)
{
final
OverlayState
overlay
=
Overlay
.
of
(
context
)!;
final
RenderBox
renderBox
=
context
.
findRenderObject
()
as
RenderBox
;
final
Offset
topLeftCornerOffset
=
renderBox
.
localToGlobal
(
Offset
.
zero
);
double
bottomPosition
=
MediaQuery
.
of
(
context
).
size
.
height
-
topLeftCornerOffset
.
dy
;
if
(
widget
.
inputOptions
.
inputToolbarMargin
!=
null
)
{
bottomPosition
-=
widget
.
inputOptions
.
inputToolbarMargin
!.
top
-
widget
.
inputOptions
.
inputToolbarMargin
!.
bottom
;
}
_clearOverlay
();
_overlayEntry
=
OverlayEntry
(
builder:
(
BuildContext
context
)
{
return
Positioned
(
width:
renderBox
.
size
.
width
,
bottom:
bottomPosition
,
child:
Container
(
constraints:
BoxConstraints
(
maxHeight:
MediaQuery
.
of
(
context
).
size
.
height
-
bottomPosition
-
MediaQuery
.
of
(
context
).
padding
.
top
-
kToolbarHeight
,
),
decoration:
BoxDecoration
(
border:
Border
(
top:
BorderSide
(
width:
0.2
,
color:
Theme
.
of
(
context
).
dividerColor
,
),
),
),
child:
Material
(
color:
Theme
.
of
(
context
).
selectedRowColor
,
child:
SingleChildScrollView
(
child:
Column
(
children:
children
,
),
),
),
),
);
},
);
overlay
.
insert
(
_overlayEntry
!);
}
void
_sendMessage
()
{
if
(
textController
.
text
.
isNotEmpty
)
{
final
ChatMessage
message
=
ChatMessage
(
text:
textController
.
text
,
user:
widget
.
currentUser
,
createdAt:
DateTime
.
now
(),
);
widget
.
onSend
(
message
);
textController
.
text
=
''
;
if
(
widget
.
inputOptions
.
onTextChange
!=
null
)
{
widget
.
inputOptions
.
onTextChange
!(
''
);
}
}
}
}
lib/package/chat_dash/src/widgets/message_list/default_date_separator.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
class
DefaultDateSeparator
extends
StatelessWidget
{
const
DefaultDateSeparator
({
required
this
.
date
,
this
.
messageListOptions
=
const
MessageListOptions
(),
this
.
padding
=
const
EdgeInsets
.
symmetric
(
vertical:
20
),
this
.
textStyle
=
const
TextStyle
(
color:
Colors
.
grey
),
Key
?
key
,
})
:
super
(
key:
key
);
/// Date to show
final
DateTime
date
;
/// Options to customize the behaviour and design of the overall list of message
final
MessageListOptions
messageListOptions
;
/// Padding of the separator
final
EdgeInsets
padding
;
/// Style of the text
final
TextStyle
textStyle
;
@override
Widget
build
(
BuildContext
context
)
{
return
Padding
(
padding:
padding
,
child:
Text
(
_formatDateSeparator
(
date
),
style:
textStyle
,
),
);
}
String
_formatDateSeparator
(
DateTime
date
)
{
if
(
messageListOptions
.
dateSeparatorFormat
!=
null
)
{
return
messageListOptions
.
dateSeparatorFormat
!.
format
(
date
);
}
final
DateTime
today
=
DateTime
.
now
();
if
(
date
.
year
!=
today
.
year
)
{
return
intl
.
DateFormat
(
'dd MMM yyyy, HH:mm'
).
format
(
date
);
}
else
if
(
date
.
month
!=
today
.
month
||
_getWeekOfYear
(
date
)
!=
_getWeekOfYear
(
today
))
{
return
intl
.
DateFormat
(
'dd MMM HH:mm'
).
format
(
date
);
}
else
if
(
date
.
day
!=
today
.
day
)
{
return
intl
.
DateFormat
(
'E HH:mm'
).
format
(
date
);
}
return
intl
.
DateFormat
(
'HH:mm'
).
format
(
date
);
}
int
_getWeekOfYear
(
DateTime
date
)
{
final
int
dayOfYear
=
int
.
parse
(
intl
.
DateFormat
(
'D'
).
format
(
date
));
return
((
dayOfYear
-
date
.
weekday
+
10
)
/
7
).
floor
();
}
}
lib/package/chat_dash/src/widgets/message_list/default_scroll_to_bottom.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
class
DefaultScrollToBottom
extends
StatelessWidget
{
const
DefaultScrollToBottom
({
required
this
.
scrollController
,
this
.
backgroundColor
,
this
.
textColor
,
this
.
bottom
=
10.0
,
this
.
left
=
0.0
,
this
.
right
=
0.0
,
this
.
top
,
this
.
height
=
30.0
,
this
.
width
=
30.0
,
this
.
elevation
=
5
,
this
.
icon
=
Icons
.
arrow_downward
,
this
.
iconSize
=
18
,
this
.
onScrollToBottomPress
,
Key
?
key
,
})
:
super
(
key:
key
);
/// Scroll controller of the chat list
final
ScrollController
scrollController
;
/// Background color of the button
final
Color
?
backgroundColor
;
/// Icon color of the button
final
Color
?
textColor
;
/// The distance that the child's bottom edge is inset from the bottom of the stack
final
double
?
bottom
;
/// The distance that the child's left edge is inset from the left of the stack
final
double
?
left
;
/// The distance that the child's right edge is inset from the right of the stack
final
double
?
right
;
/// The distance that the child's top edge is inset from the top of the stack
final
double
?
top
;
/// Height of the button
final
double
height
;
/// Width of the button
final
double
width
;
/// Elevation of the button
final
double
elevation
;
/// Icon of the button
final
IconData
icon
;
/// Icon size
final
double
iconSize
;
/// Function to call when the scroll-to-bottom widget is pressed
/// It will scroll down in any case
final
void
Function
()?
onScrollToBottomPress
;
@override
Widget
build
(
BuildContext
context
)
{
return
Positioned
(
right:
right
,
left:
left
,
top:
top
,
bottom:
bottom
,
child:
SizedBox
(
width:
width
,
height:
height
,
child:
RawMaterialButton
(
elevation:
elevation
,
fillColor:
backgroundColor
,
shape:
const
CircleBorder
(),
child:
Icon
(
icon
,
size:
iconSize
,
color:
textColor
,
),
onPressed:
()
{
if
(
onScrollToBottomPress
!=
null
)
{
onScrollToBottomPress
!();
}
scrollController
.
animateTo
(
0.0
,
duration:
const
Duration
(
milliseconds:
300
),
curve:
Curves
.
easeInOut
,
);
},
),
),
);
}
}
lib/package/chat_dash/src/widgets/message_list/message_list.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
MessageList
extends
StatefulWidget
{
const
MessageList
({
required
this
.
currentUser
,
required
this
.
messages
,
this
.
messageOptions
=
const
MessageOptions
(),
this
.
messageListOptions
=
const
MessageListOptions
(),
this
.
quickReplyOptions
=
const
QuickReplyOptions
(),
this
.
scrollToBottomOptions
=
const
ScrollToBottomOptions
(),
this
.
typingUsers
,
Key
?
key
,
})
:
super
(
key:
key
);
/// The current user of the chat
final
ChatUser
currentUser
;
/// List of messages visible in the chat
final
List
<
ChatMessage
>
messages
;
/// Options to customize the behaviour and design of the messages
final
MessageOptions
messageOptions
;
/// Options to customize the behaviour and design of the overall list of message
final
MessageListOptions
messageListOptions
;
/// Options to customize the behaviour and design of the quick replies
final
QuickReplyOptions
quickReplyOptions
;
/// Options to customize the behaviour and design of the scroll-to-bottom button
final
ScrollToBottomOptions
scrollToBottomOptions
;
/// List of users currently typing in the chat
final
List
<
ChatUser
>?
typingUsers
;
@override
_MessageListState
createState
()
=>
_MessageListState
();
}
class
_MessageListState
extends
State
<
MessageList
>
{
bool
scrollToBottomIsVisible
=
false
;
bool
isLoadingMore
=
false
;
late
ScrollController
scrollController
;
@override
void
initState
()
{
scrollController
=
widget
.
messageListOptions
.
scrollController
??
ScrollController
();
scrollController
.
addListener
(()
=>
_onScroll
());
super
.
initState
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
()
=>
FocusScope
.
of
(
context
).
requestFocus
(
FocusNode
()),
child:
Stack
(
children:
<
Widget
>[
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
<
Widget
>[
Expanded
(
child:
ListView
.
builder
(
physics:
widget
.
messageListOptions
.
scrollPhysics
,
controller:
scrollController
,
reverse:
true
,
itemCount:
widget
.
messages
.
length
,
itemBuilder:
(
BuildContext
context
,
int
i
)
{
final
ChatMessage
?
previousMessage
=
i
<
widget
.
messages
.
length
-
1
?
widget
.
messages
[
i
+
1
]
:
null
;
final
ChatMessage
?
nextMessage
=
i
>
0
?
widget
.
messages
[
i
-
1
]
:
null
;
final
ChatMessage
message
=
widget
.
messages
[
i
];
final
bool
isAfterDateSeparator
=
_shouldShowDateSeparator
(
previousMessage
,
message
,
widget
.
messageListOptions
);
bool
isBeforeDateSeparator
=
false
;
if
(
nextMessage
!=
null
)
{
isBeforeDateSeparator
=
_shouldShowDateSeparator
(
message
,
nextMessage
,
widget
.
messageListOptions
);
}
return
Column
(
children:
<
Widget
>[
if
(
isAfterDateSeparator
)
widget
.
messageListOptions
.
dateSeparatorBuilder
!=
null
?
widget
.
messageListOptions
.
dateSeparatorBuilder
!(
message
.
createdAt
)
:
DefaultDateSeparator
(
date:
message
.
createdAt
,
messageListOptions:
widget
.
messageListOptions
,
),
if
(
widget
.
messageOptions
.
messageRowBuilder
!=
null
)
...<
Widget
>[
widget
.
messageOptions
.
messageRowBuilder
!(
message
,
previousMessage
,
nextMessage
,
isAfterDateSeparator
,
isBeforeDateSeparator
,
),
]
else
MessageRow
(
message:
widget
.
messages
[
i
],
nextMessage:
nextMessage
,
previousMessage:
previousMessage
,
currentUser:
widget
.
currentUser
,
isAfterDateSeparator:
isAfterDateSeparator
,
isBeforeDateSeparator:
isBeforeDateSeparator
,
messageOptions:
widget
.
messageOptions
,
messageLength:
widget
.
messages
,
),
],
);
},
),
),
if
(
widget
.
typingUsers
!=
null
&&
widget
.
typingUsers
!.
isNotEmpty
)
...
widget
.
typingUsers
!.
map
((
ChatUser
user
)
{
if
(
widget
.
messageListOptions
.
typingBuilder
!=
null
)
{
return
widget
.
messageListOptions
.
typingBuilder
!(
user
);
}
return
DefaultTypingBuilder
(
user:
user
);
}).
toList
(),
if
(
widget
.
messageListOptions
.
showFooterBeforeQuickReplies
&&
widget
.
messageListOptions
.
chatFooterBuilder
!=
null
)
widget
.
messageListOptions
.
chatFooterBuilder
!,
if
(
widget
.
messages
.
isNotEmpty
&&
widget
.
messages
.
first
.
quickReplies
!=
null
&&
widget
.
messages
.
first
.
quickReplies
!.
isNotEmpty
&&
widget
.
messages
.
first
.
user
.
id
!=
widget
.
currentUser
.
id
)
QuickReplies
(
quickReplies:
widget
.
messages
.
first
.
quickReplies
!,
quickReplyOptions:
widget
.
quickReplyOptions
,
),
if
(!
widget
.
messageListOptions
.
showFooterBeforeQuickReplies
&&
widget
.
messageListOptions
.
chatFooterBuilder
!=
null
)
widget
.
messageListOptions
.
chatFooterBuilder
!,
],
),
if
(
isLoadingMore
)
Positioned
(
top:
8.0
,
right:
0
,
left:
0
,
child:
widget
.
messageListOptions
.
loadEarlierBuilder
??
const
Center
(
child:
SizedBox
(
child:
CircularProgressIndicator
(),
),
),
),
if
(!
widget
.
scrollToBottomOptions
.
disabled
&&
scrollToBottomIsVisible
)
widget
.
scrollToBottomOptions
.
scrollToBottomBuilder
!=
null
?
widget
.
scrollToBottomOptions
.
scrollToBottomBuilder
!(
scrollController
)
:
DefaultScrollToBottom
(
scrollController:
scrollController
,
backgroundColor:
Theme
.
of
(
context
).
scaffoldBackgroundColor
,
textColor:
Theme
.
of
(
context
).
primaryColor
,
),
],
),
);
}
/// Check if a date separator needs to be shown
bool
_shouldShowDateSeparator
(
ChatMessage
?
previousMessage
,
ChatMessage
message
,
MessageListOptions
messageListOptions
)
{
if
(!
messageListOptions
.
showDateSeparator
)
{
return
false
;
}
if
(
previousMessage
==
null
)
{
// Means this is the first message
return
true
;
}
switch
(
messageListOptions
.
separatorFrequency
)
{
case
SeparatorFrequency
.
days
:
final
DateTime
previousDate
=
DateTime
(
previousMessage
.
createdAt
.
year
,
previousMessage
.
createdAt
.
month
,
previousMessage
.
createdAt
.
day
,
);
final
DateTime
messageDate
=
DateTime
(
message
.
createdAt
.
year
,
message
.
createdAt
.
month
,
message
.
createdAt
.
day
,
);
return
previousDate
.
difference
(
messageDate
).
inDays
.
abs
()
>
0
;
case
SeparatorFrequency
.
hours
:
final
DateTime
previousDate
=
DateTime
(
previousMessage
.
createdAt
.
year
,
previousMessage
.
createdAt
.
month
,
previousMessage
.
createdAt
.
day
,
previousMessage
.
createdAt
.
hour
,
);
final
DateTime
messageDate
=
DateTime
(
message
.
createdAt
.
year
,
message
.
createdAt
.
month
,
message
.
createdAt
.
day
,
message
.
createdAt
.
hour
,
);
return
previousDate
.
difference
(
messageDate
).
inHours
.
abs
()
>
0
;
default
:
return
false
;
}
}
/// Sroll listener to trigger different actions:
/// show scroll-to-bottom btn and LoadEarlier behaviour
Future
<
void
>
_onScroll
()
async
{
bool
topReached
=
scrollController
.
offset
>=
scrollController
.
position
.
maxScrollExtent
&&
!
scrollController
.
position
.
outOfRange
;
if
(
topReached
&&
widget
.
messageListOptions
.
onLoadEarlier
!=
null
&&
!
isLoadingMore
)
{
setState
(()
{
isLoadingMore
=
true
;
});
showScrollToBottom
();
await
widget
.
messageListOptions
.
onLoadEarlier
!();
setState
(()
{
isLoadingMore
=
false
;
});
}
else
if
(
scrollController
.
offset
>
200
)
{
showScrollToBottom
();
}
else
{
hideScrollToBottom
();
}
}
void
showScrollToBottom
()
{
if
(!
scrollToBottomIsVisible
)
{
setState
(()
{
scrollToBottomIsVisible
=
true
;
});
}
}
void
hideScrollToBottom
()
{
if
(
scrollToBottomIsVisible
)
{
setState
(()
{
scrollToBottomIsVisible
=
false
;
});
}
}
}
lib/package/chat_dash/src/widgets/message_row/default_avatar.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
class
DefaultAvatar
extends
StatelessWidget
{
const
DefaultAvatar
({
required
this
.
user
,
this
.
size
=
35
,
this
.
fallbackImage
,
this
.
onPressAvatar
,
this
.
onLongPressAvatar
,
});
/// The URL of the user's profile picture
final
ChatUser
user
;
/// Size of the avatar
final
double
size
;
/// Placeholder image in case there is no initials ot he profile image do not load
final
ImageProvider
?
fallbackImage
;
/// Function to call when the user long press on the avatar
final
void
Function
(
ChatUser
)?
onLongPressAvatar
;
/// Function to call when the user press on the avatar
final
void
Function
(
ChatUser
)?
onPressAvatar
;
/// Get the initials of the user
String
getInitials
()
{
return
(
user
.
firstName
==
null
||
user
.
firstName
!.
isEmpty
?
''
:
user
.
firstName
![
0
])
+
(
user
.
lastName
==
null
||
user
.
lastName
!.
isEmpty
?
''
:
user
.
lastName
![
0
]);
}
@override
Widget
build
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
onPressAvatar
!=
null
?
()
=>
onPressAvatar
!(
user
)
:
null
,
onLongPress:
onLongPressAvatar
!=
null
?
()
=>
onLongPressAvatar
!(
user
)
:
null
,
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
10
,
),
child:
SizedBox
(
height:
size
,
width:
size
,
child:
Stack
(
alignment:
Alignment
.
center
,
children:
<
Widget
>[
ClipOval
(
child:
Container
(
color:
Colors
.
grey
[
200
],
child:
getInitials
().
isNotEmpty
?
Center
(
child:
Text
(
getInitials
(),
style:
TextStyle
(
color:
Colors
.
black
,
fontSize:
size
*
0.35
,
),
),
)
:
Image
(
image:
fallbackImage
??
const
AssetImage
(
'assets/profile_placeholder.png'
,
package:
'dash_chat_2'
,
),
),
),
),
if
(
user
.
profileImage
!=
null
&&
user
.
profileImage
!.
isNotEmpty
)
Center
(
child:
ClipOval
(
child:
FadeInImage
(
width:
size
,
height:
size
,
fit:
BoxFit
.
cover
,
image:
getImageProvider
(
user
.
profileImage
!),
placeholder:
fallbackImage
??
const
AssetImage
(
'assets/profile_placeholder.png'
,
package:
'dash_chat_2'
,
),
),
),
),
],
),
),
),
);
}
}
lib/package/chat_dash/src/widgets/message_row/default_message_decoration.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
BoxDecoration
defaultMessageDecoration
(
{
required
Color
color
,
required
double
borderTopLeft
,
required
double
borderTopRight
,
required
double
borderBottomLeft
,
required
double
borderBottomRight
,
})
=>
BoxDecoration
(
color:
color
,
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
borderTopLeft
),
topRight:
Radius
.
circular
(
borderTopRight
),
bottomLeft:
Radius
.
circular
(
borderBottomLeft
),
bottomRight:
Radius
.
circular
(
borderBottomRight
),
),
);
lib/package/chat_dash/src/widgets/message_row/default_message_text.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
// part of animated_text_kit;
/// {@category Default widgets}
class
DefaultMessageText
extends
StatelessWidget
{
const
DefaultMessageText
({
required
this
.
message
,
required
this
.
messageLength
,
required
this
.
isOwnMessage
,
this
.
messageOptions
=
const
MessageOptions
(),
Key
?
key
,
})
:
super
(
key:
key
);
final
List
<
ChatMessage
>
messageLength
;
/// Message tha contains the text to show
final
ChatMessage
message
;
/// If the message is from the current user
final
bool
isOwnMessage
;
/// Options to customize the behaviour and design of the messages
final
MessageOptions
messageOptions
;
@override
Widget
build
(
BuildContext
context
)
{
return
Column
(
crossAxisAlignment:
isOwnMessage
?
CrossAxisAlignment
.
end
:
CrossAxisAlignment
.
start
,
children:
<
Widget
>[
Wrap
(
children:
getMessage
(
isOwnMessage
,
messageLength
),
),
if
(
messageOptions
.
showTime
)
messageOptions
.
messageTimeBuilder
!=
null
?
messageOptions
.
messageTimeBuilder
!(
message
,
isOwnMessage
)
:
Padding
(
padding:
const
EdgeInsets
.
only
(
top:
5
),
child:
Text
(
(
messageOptions
.
timeFormat
??
intl
.
DateFormat
(
'HH:mm'
))
.
format
(
message
.
createdAt
),
style:
TextStyle
(
color:
isOwnMessage
?
(
messageOptions
.
currentUserTextColor
??
Colors
.
white70
)
:
(
messageOptions
.
textColor
??
Colors
.
black54
),
fontSize:
10
,
),
),
),
],
);
}
List
<
Widget
>
getMessage
(
bool
isOwnMessage
,
List
<
ChatMessage
>
messageLength
)
{
if
(
message
.
mentions
!=
null
&&
message
.
mentions
!.
isNotEmpty
)
{
String
stringRegex
=
r'([\s\S]*)'
;
String
stringMentionRegex
=
''
;
for
(
final
Mention
mention
in
message
.
mentions
!)
{
stringRegex
+=
'(
${mention.title}
)'
r'([\s\S]*)'
;
stringMentionRegex
+=
stringMentionRegex
.
isEmpty
?
'(
${mention.title}
)'
:
'|(
${mention.title}
)'
;
}
final
RegExp
mentionRegex
=
RegExp
(
stringMentionRegex
);
final
RegExp
regexp
=
RegExp
(
stringRegex
);
RegExpMatch
?
match
=
regexp
.
firstMatch
(
message
.
text
);
if
(
match
!=
null
)
{
List
<
Widget
>
res
=
<
Widget
>[];
match
.
groups
(
List
<
int
>.
generate
(
match
.
groupCount
,
(
int
i
)
=>
i
+
1
))
.
forEach
((
String
?
part
)
{
if
(
mentionRegex
.
hasMatch
(
part
!))
{
Mention
mention
=
message
.
mentions
!.
firstWhere
(
(
Mention
m
)
=>
m
.
title
==
part
,
);
res
.
add
(
getMention
(
mention
));
}
else
{
res
.
add
(
getParsePattern
(
part
,
false
,
messageLength
));
}
});
if
(
res
.
isNotEmpty
)
{
return
res
;
}
}
}
return
<
Widget
>[
getParsePattern
(
message
.
text
,
isOwnMessage
,
messageLength
)];
}
Widget
getPostMessageBuild
(
String
text
,
List
<
ChatMessage
>
messageLength
,
bool
isOwnMessage
)
{
var
lastMessage
=
messageLength
.
last
;
// if(lastMessage.) {
// }
// messageLength[messageLength.length - 1];
// if(a.is)
// if()
return
AnimatedTextKit
(
animatedTexts:
[
TypewriterAnimatedText
(
text
,
textStyle:
const
TextStyle
(
// fontSize: 32.0,
// fontWeight: FontWeight.bold,
),
speed:
const
Duration
(
milliseconds:
100
),
)
],
totalRepeatCount:
1
,
// displayFullTextOnTap: true,
// stopPauseOnTap: true,
);
}
// {buildPostMessage = getPostMessageBuild}
Widget
getParsePattern
(
String
text
,
bool
isOwnMessage
,
List
<
ChatMessage
>
messageLength
,
)
{
return
!
isOwnMessage
?
getPostMessageBuild
(
text
,
messageLength
,
isOwnMessage
)
:
ParsedText
(
parse:
messageOptions
.
parsePatterns
!=
null
?
messageOptions
.
parsePatterns
!
:
defaultPersePatterns
,
text:
text
,
style:
TextStyle
(
color:
isOwnMessage
?
(
messageOptions
.
currentUserTextColor
??
Colors
.
white
)
:
(
messageOptions
.
textColor
??
Colors
.
black
),
),
);
}
Widget
getMention
(
Mention
mention
)
{
return
RichText
(
text:
TextSpan
(
text:
mention
.
title
,
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
=>
messageOptions
.
onPressMention
!=
null
?
messageOptions
.
onPressMention
!(
mention
)
:
null
,
style:
TextStyle
(
color:
isOwnMessage
?
(
messageOptions
.
currentUserTextColor
??
Colors
.
white
)
:
(
messageOptions
.
textColor
??
Colors
.
black
),
decoration:
TextDecoration
.
none
,
fontWeight:
FontWeight
.
w600
,
),
),
);
}
}
lib/package/chat_dash/src/widgets/message_row/default_parse_patterns.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
List
<
MatchText
>
defaultPersePatterns
=
<
MatchText
>[
MatchText
(
type:
ParsedType
.
URL
,
style:
const
TextStyle
(
decoration:
TextDecoration
.
underline
,
),
onTap:
(
String
url
)
{
if
(!
url
.
startsWith
(
'http://'
)
&&
!
url
.
startsWith
(
'https://'
))
{
url
=
'http://'
+
url
;
}
launchUrl
(
Uri
.
parse
(
url
),
mode:
LaunchMode
.
externalApplication
);
},
),
];
lib/package/chat_dash/src/widgets/message_row/default_user_name.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
class
DefaultUserName
extends
StatelessWidget
{
const
DefaultUserName
({
required
this
.
user
,
this
.
style
,
this
.
padding
,
Key
?
key
,
})
:
super
(
key:
key
);
/// User to show
final
ChatUser
user
;
/// Style of the text
final
TextStyle
?
style
;
/// Padding around the text
final
EdgeInsets
?
padding
;
@override
Widget
build
(
BuildContext
context
)
{
return
Padding
(
padding:
padding
??
const
EdgeInsets
.
symmetric
(
horizontal:
10
),
child:
Text
(
user
.
getFullName
(),
style:
style
??
const
TextStyle
(
fontSize:
10
,
color:
Colors
.
grey
,
),
),
);
}
}
lib/package/chat_dash/src/widgets/message_row/media_container.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
MediaContainer
extends
StatelessWidget
{
const
MediaContainer
({
required
this
.
message
,
required
this
.
isOwnMessage
,
required
this
.
messageLength
,
this
.
messageOptions
=
const
MessageOptions
(),
Key
?
key
,
})
:
super
(
key:
key
);
/// Message that contains the media to show
final
ChatMessage
message
;
final
List
<
ChatMessage
>
messageLength
;
/// If the message is from the current user
final
bool
isOwnMessage
;
/// Options to customize the behaviour and design of the messages
final
MessageOptions
messageOptions
;
/// Get the right media widget according to its type
Widget
_getMedia
(
ChatMedia
media
,
double
?
height
,
double
?
width
)
{
final
Widget
loading
=
Container
(
width:
15
,
height:
15
,
margin:
const
EdgeInsets
.
all
(
10
),
child:
const
CircularProgressIndicator
(),
);
switch
(
media
.
type
)
{
case
MediaType
.
video
:
return
Stack
(
alignment:
AlignmentDirectional
.
bottomEnd
,
children:
<
Widget
>[
VideoPlayer
(
url:
media
.
url
,
key:
GlobalKey
()),
if
(
media
.
isUploading
)
loading
],
);
case
MediaType
.
image
:
return
Stack
(
alignment:
AlignmentDirectional
.
bottomEnd
,
children:
<
Widget
>[
Image
(
height:
height
,
width:
width
,
fit:
BoxFit
.
cover
,
alignment:
isOwnMessage
?
Alignment
.
topRight
:
Alignment
.
topLeft
,
image:
getImageProvider
(
media
.
url
),
),
if
(
media
.
isUploading
)
loading
],
);
default
:
return
TextContainer
(
isOwnMessage:
isOwnMessage
,
messageOptions:
messageOptions
,
message:
message
,
messageLength:
messageLength
,
messageTextBuilder:
(
ChatMessage
m
,
ChatMessage
?
p
,
ChatMessage
?
n
)
{
return
Row
(
children:
<
Widget
>[
Padding
(
padding:
const
EdgeInsets
.
only
(
right:
8.0
),
child:
!
media
.
isUploading
?
Icon
(
Icons
.
description
,
size:
18
,
color:
isOwnMessage
?
(
messageOptions
.
currentUserTextColor
??
Colors
.
white
)
:
(
messageOptions
.
textColor
??
Colors
.
black
),
)
:
loading
,
),
Flexible
(
child:
Text
(
media
.
fileName
,
style:
TextStyle
(
decoration:
TextDecoration
.
underline
,
color:
isOwnMessage
?
(
messageOptions
.
currentUserTextColor
??
Colors
.
white
)
:
(
messageOptions
.
textColor
??
Colors
.
black
),
),
),
),
],
);
},
);
}
}
@override
Widget
build
(
BuildContext
context
)
{
if
(
message
.
medias
!=
null
&&
message
.
medias
!.
isNotEmpty
)
{
final
List
<
ChatMedia
>
media
=
message
.
medias
!;
return
Wrap
(
alignment:
isOwnMessage
?
WrapAlignment
.
end
:
WrapAlignment
.
start
,
children:
media
.
map
(
(
ChatMedia
m
)
{
final
double
gallerySize
=
(
MediaQuery
.
of
(
context
).
size
.
width
*
0.7
)
/
2
-
5
;
final
bool
isImage
=
m
.
type
==
MediaType
.
image
;
return
Container
(
color:
Colors
.
transparent
,
margin:
const
EdgeInsets
.
only
(
top:
5
,
right:
5
),
width:
media
.
length
>
1
&&
isImage
?
gallerySize
:
null
,
height:
media
.
length
>
1
&&
isImage
?
gallerySize
:
null
,
constraints:
BoxConstraints
(
maxHeight:
MediaQuery
.
of
(
context
).
size
.
height
*
0.5
,
maxWidth:
MediaQuery
.
of
(
context
).
size
.
width
*
0.7
,
),
child:
GestureDetector
(
onTap:
messageOptions
.
onTapMedia
!=
null
?
()
=>
messageOptions
.
onTapMedia
!(
m
)
:
null
,
child:
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
8.0
),
child:
ColorFiltered
(
colorFilter:
ColorFilter
.
mode
(
m
.
isUploading
?
Colors
.
white54
:
Colors
.
white
.
withOpacity
(
0.1
,
),
// Because transparent is causing an issue on flutter web
BlendMode
.
srcATop
,
),
child:
_getMedia
(
m
,
media
.
length
>
1
?
gallerySize
:
null
,
media
.
length
>
1
?
gallerySize
:
null
,
),
),
),
),
);
},
).
toList
(),
);
}
return
const
SizedBox
();
}
}
lib/package/chat_dash/src/widgets/message_row/message_row.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
MessageRow
extends
StatelessWidget
{
const
MessageRow
({
required
this
.
message
,
required
this
.
currentUser
,
required
this
.
messageLength
,
this
.
previousMessage
,
this
.
nextMessage
,
this
.
isAfterDateSeparator
=
false
,
this
.
isBeforeDateSeparator
=
false
,
this
.
messageOptions
=
const
MessageOptions
(),
Key
?
key
,
})
:
super
(
key:
key
);
final
List
<
ChatMessage
>
messageLength
;
/// Current message to show
final
ChatMessage
message
;
/// Previous message in the list
final
ChatMessage
?
previousMessage
;
/// Next message in the list
final
ChatMessage
?
nextMessage
;
/// Current user of the chat
final
ChatUser
currentUser
;
/// If the message is preceded by a date separator
final
bool
isAfterDateSeparator
;
/// If the message is before a date separator
final
bool
isBeforeDateSeparator
;
/// Options to customize the behaviour and design of the messages
final
MessageOptions
messageOptions
;
/// Get the avatar widget
Widget
getAvatar
()
{
return
messageOptions
.
avatarBuilder
!=
null
?
messageOptions
.
avatarBuilder
!(
message
.
user
,
messageOptions
.
onPressAvatar
,
messageOptions
.
onLongPressAvatar
,
)
:
DefaultAvatar
(
user:
message
.
user
,
onLongPressAvatar:
messageOptions
.
onLongPressAvatar
,
onPressAvatar:
messageOptions
.
onPressAvatar
,
);
}
@override
Widget
build
(
BuildContext
context
)
{
print
(
"messageLengthmessageLength
$messageLength
"
);
final
bool
isOwnMessage
=
message
.
user
.
id
==
currentUser
.
id
;
bool
isPreviousSameAuthor
=
false
;
bool
isNextSameAuthor
=
false
;
if
(
previousMessage
!=
null
&&
previousMessage
!.
user
.
id
==
message
.
user
.
id
)
{
isPreviousSameAuthor
=
true
;
}
if
(
nextMessage
!=
null
&&
nextMessage
!.
user
.
id
==
message
.
user
.
id
)
{
isNextSameAuthor
=
true
;
}
return
Padding
(
padding:
EdgeInsets
.
only
(
top:
isPreviousSameAuthor
?
2
:
15
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
mainAxisAlignment:
isOwnMessage
?
MainAxisAlignment
.
end
:
MainAxisAlignment
.
start
,
children:
<
Widget
>[
if
(
messageOptions
.
showOtherUsersAvatar
)
Opacity
(
opacity:
!
isOwnMessage
&&
(!
isNextSameAuthor
||
isBeforeDateSeparator
)
?
1
:
0
,
child:
getAvatar
(),
),
if
(!
messageOptions
.
showOtherUsersAvatar
)
const
Padding
(
padding:
EdgeInsets
.
only
(
left:
10
)),
GestureDetector
(
onLongPress:
messageOptions
.
onLongPressMessage
!=
null
?
()
=>
messageOptions
.
onLongPressMessage
!(
message
)
:
null
,
onTap:
messageOptions
.
onPressMessage
!=
null
?
()
=>
messageOptions
.
onPressMessage
!(
message
)
:
null
,
child:
ConstrainedBox
(
constraints:
BoxConstraints
(
maxWidth:
messageOptions
.
maxWidth
??
MediaQuery
.
of
(
context
).
size
.
width
*
0.7
,
),
child:
Column
(
crossAxisAlignment:
isOwnMessage
?
CrossAxisAlignment
.
end
:
CrossAxisAlignment
.
start
,
mainAxisAlignment:
MainAxisAlignment
.
end
,
children:
<
Widget
>[
if
(
messageOptions
.
top
!=
null
)
messageOptions
.
top
!(
message
,
previousMessage
,
nextMessage
),
if
(!
isOwnMessage
&&
messageOptions
.
showOtherUsersName
&&
(!
isPreviousSameAuthor
||
isAfterDateSeparator
))
messageOptions
.
userNameBuilder
!=
null
?
messageOptions
.
userNameBuilder
!(
message
.
user
)
:
DefaultUserName
(
user:
message
.
user
),
if
(
message
.
medias
!=
null
&&
message
.
medias
!.
isNotEmpty
&&
messageOptions
.
textBeforeMedia
)
messageOptions
.
messageMediaBuilder
!=
null
?
messageOptions
.
messageMediaBuilder
!(
message
,
previousMessage
,
nextMessage
)
:
MediaContainer
(
message:
message
,
isOwnMessage:
isOwnMessage
,
messageOptions:
messageOptions
,
messageLength:
messageLength
,
// messageLength: messageLength,
),
if
(
message
.
text
.
isNotEmpty
)
TextContainer
(
messageOptions:
messageOptions
,
message:
message
,
messageLength:
messageLength
,
previousMessage:
previousMessage
,
nextMessage:
nextMessage
,
isOwnMessage:
isOwnMessage
,
isNextSameAuthor:
isNextSameAuthor
,
isPreviousSameAuthor:
isPreviousSameAuthor
,
isAfterDateSeparator:
isAfterDateSeparator
,
isBeforeDateSeparator:
isBeforeDateSeparator
,
messageTextBuilder:
messageOptions
.
messageTextBuilder
,
),
if
(
message
.
medias
!=
null
&&
message
.
medias
!.
isNotEmpty
&&
!
messageOptions
.
textBeforeMedia
)
messageOptions
.
messageMediaBuilder
!=
null
?
messageOptions
.
messageMediaBuilder
!(
message
,
previousMessage
,
nextMessage
)
:
MediaContainer
(
message:
message
,
isOwnMessage:
isOwnMessage
,
messageOptions:
messageOptions
,
messageLength:
messageLength
,
),
if
(
messageOptions
.
bottom
!=
null
)
messageOptions
.
bottom
!(
message
,
previousMessage
,
nextMessage
),
],
),
),
),
if
(
messageOptions
.
showCurrentUserAvatar
)
Opacity
(
opacity:
isOwnMessage
&&
!
isNextSameAuthor
?
1
:
0
,
child:
getAvatar
(),
),
if
(!
messageOptions
.
showCurrentUserAvatar
)
const
Padding
(
padding:
EdgeInsets
.
only
(
left:
10
))
],
),
);
}
}
lib/package/chat_dash/src/widgets/message_row/text_container.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
TextContainer
extends
StatelessWidget
{
const
TextContainer
({
required
this
.
message
,
this
.
messageOptions
=
const
MessageOptions
(),
this
.
previousMessage
,
this
.
nextMessage
,
required
this
.
messageLength
,
this
.
isOwnMessage
=
false
,
this
.
isPreviousSameAuthor
=
false
,
this
.
isNextSameAuthor
=
false
,
this
.
isAfterDateSeparator
=
false
,
this
.
isBeforeDateSeparator
=
false
,
this
.
messageTextBuilder
,
Key
?
key
,
})
:
super
(
key:
key
);
final
List
<
ChatMessage
>
messageLength
;
/// Options to customize the behaviour and design of the messages
final
MessageOptions
messageOptions
;
/// Message that contains the text to show
final
ChatMessage
message
;
/// Previous message in the list
final
ChatMessage
?
previousMessage
;
/// Next message in the list
final
ChatMessage
?
nextMessage
;
/// If the message is from the current user
final
bool
isOwnMessage
;
/// If the previous message is from the same author as the current one
final
bool
isPreviousSameAuthor
;
/// If the next message is from the same author as the current one
final
bool
isNextSameAuthor
;
/// If the message is preceded by a date separator
final
bool
isAfterDateSeparator
;
/// If the message is before by a date separator
final
bool
isBeforeDateSeparator
;
/// We could acces that from messageOptions but we want to reuse this widget
/// for media and be able to override the text builder
final
Widget
Function
(
ChatMessage
,
ChatMessage
?,
ChatMessage
?)?
messageTextBuilder
;
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
decoration:
messageOptions
.
messageDecorationBuilder
!=
null
?
messageOptions
.
messageDecorationBuilder
!(
message
,
previousMessage
,
nextMessage
)
:
defaultMessageDecoration
(
color:
isOwnMessage
?
(
messageOptions
.
currentUserContainerColor
??
Theme
.
of
(
context
).
primaryColor
)
:
(
messageOptions
.
containerColor
??
Colors
.
grey
[
100
])!,
borderTopLeft:
isPreviousSameAuthor
&&
!
isOwnMessage
&&
!
isAfterDateSeparator
?
0.0
:
18.0
,
borderTopRight:
isPreviousSameAuthor
&&
isOwnMessage
&&
!
isAfterDateSeparator
?
0.0
:
18.0
,
borderBottomLeft:
!
isOwnMessage
&&
!
isBeforeDateSeparator
&&
isNextSameAuthor
?
0.0
:
18.0
,
borderBottomRight:
isOwnMessage
&&
!
isBeforeDateSeparator
&&
isNextSameAuthor
?
0.0
:
18.0
,
),
padding:
messageOptions
.
messagePadding
??
const
EdgeInsets
.
all
(
11
),
child:
messageTextBuilder
!=
null
?
messageTextBuilder
!(
message
,
previousMessage
,
nextMessage
)
:
DefaultMessageText
(
messageLength:
messageLength
,
message:
message
,
isOwnMessage:
isOwnMessage
,
messageOptions:
messageOptions
,
),
);
}
}
lib/package/chat_dash/src/widgets/message_row/video_player.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
VideoPlayer
extends
StatefulWidget
{
const
VideoPlayer
({
required
this
.
url
,
this
.
aspectRatio
=
1
,
this
.
canPlay
=
true
,
Key
?
key
,
})
:
super
(
key:
key
);
/// Link of the video
final
String
url
;
/// The Aspect Ratio of the Video. Important to get the correct size of the video
final
double
aspectRatio
;
/// If the video can be played
final
bool
canPlay
;
@override
_VideoPlayerState
createState
()
=>
_VideoPlayerState
();
}
class
_VideoPlayerState
extends
State
<
VideoPlayer
>
{
late
vp
.
VideoPlayerController
_controller
;
@override
void
initState
()
{
super
.
initState
();
_controller
=
vp
.
VideoPlayerController
.
network
(
widget
.
url
)
..
initialize
().
then
((
_
)
{
// Ensure the first frame is shown after the video is initialized,
// even before the play button has been pressed.
setState
(()
{});
});
}
@override
void
dispose
()
{
super
.
dispose
();
_controller
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
_controller
.
value
.
isInitialized
?
Container
(
color:
Colors
.
black
,
child:
Stack
(
alignment:
_controller
.
value
.
isPlaying
?
AlignmentDirectional
.
bottomStart
:
AlignmentDirectional
.
center
,
children:
<
Widget
>[
AspectRatio
(
aspectRatio:
_controller
.
value
.
aspectRatio
,
child:
vp
.
VideoPlayer
(
_controller
),
),
IconButton
(
iconSize:
_controller
.
value
.
isPlaying
?
24
:
60
,
onPressed:
widget
.
canPlay
?
()
{
setState
(()
{
_controller
.
value
.
isPlaying
?
_controller
.
pause
()
:
_controller
.
play
();
});
}
:
null
,
icon:
Icon
(
_controller
.
value
.
isPlaying
?
Icons
.
pause
:
Icons
.
play_arrow
,
color:
Colors
.
white
,
// size: 60,
),
),
],
),
)
:
Container
(
color:
Colors
.
black
);
}
}
lib/package/chat_dash/src/widgets/quick_replies/default_quick_reply.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
class
DefaultQuickReply
extends
StatelessWidget
{
const
DefaultQuickReply
({
required
this
.
quickReply
,
this
.
quickReplyOptions
=
const
QuickReplyOptions
(),
Key
?
key
,
})
:
super
(
key:
key
);
/// Options used to customize quick replies behaviour and design
final
QuickReplyOptions
quickReplyOptions
;
/// Quick reply to show
final
QuickReply
quickReply
;
@override
Widget
build
(
BuildContext
context
)
{
return
GestureDetector
(
onTap:
quickReplyOptions
.
onTapQuickReply
!=
null
?
()
=>
quickReplyOptions
.
onTapQuickReply
!(
quickReply
)
:
null
,
child:
Container
(
margin:
quickReplyOptions
.
quickReplyMargin
??
const
EdgeInsets
.
symmetric
(
horizontal:
5
),
padding:
quickReplyOptions
.
quickReplyPadding
??
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
5
),
decoration:
quickReplyOptions
.
quickReplyStyle
??
BoxDecoration
(
border:
Border
.
all
(
color:
Theme
.
of
(
context
).
primaryColor
),
borderRadius:
const
BorderRadius
.
all
(
Radius
.
circular
(
5.0
)),
),
child:
Text
(
quickReply
.
title
,
style:
quickReplyOptions
.
quickReplyTextStyle
??
TextStyle
(
color:
Theme
.
of
(
context
).
primaryColor
),
),
),
);
}
}
lib/package/chat_dash/src/widgets/quick_replies/quick_replies.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
QuickReplies
extends
StatelessWidget
{
const
QuickReplies
({
required
this
.
quickReplies
,
this
.
quickReplyOptions
=
const
QuickReplyOptions
(),
Key
?
key
,
})
:
super
(
key:
key
);
/// List of quick replies to show
final
List
<
QuickReply
>
quickReplies
;
/// Options used to customize quick replies behaviour and design
final
QuickReplyOptions
quickReplyOptions
;
@override
Widget
build
(
BuildContext
context
)
{
return
Column
(
mainAxisSize:
MainAxisSize
.
min
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
<
Widget
>[
SingleChildScrollView
(
scrollDirection:
Axis
.
horizontal
,
child:
Padding
(
padding:
const
EdgeInsets
.
all
(
8.0
),
child:
Row
(
children:
quickReplies
.
map
((
QuickReply
r
)
{
return
quickReplyOptions
.
quickReplyBuilder
!=
null
?
quickReplyOptions
.
quickReplyBuilder
!(
r
)
:
DefaultQuickReply
(
quickReply:
r
,
quickReplyOptions:
quickReplyOptions
,
);
}).
toList
(),
),
),
),
],
);
}
}
lib/package/chat_dash/src/widgets/typing_users/default_typing_builder.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// {@category Default widgets}
class
DefaultTypingBuilder
extends
StatelessWidget
{
const
DefaultTypingBuilder
({
required
this
.
user
,
this
.
text
=
'is typing'
,
Key
?
key
,
})
:
super
(
key:
key
);
/// User that is typing
final
ChatUser
user
;
/// Text to show after user's name in the indicator
final
String
text
;
@override
Widget
build
(
BuildContext
context
)
{
return
Padding
(
padding:
const
EdgeInsets
.
only
(
left:
15
,
top:
25
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
children:
<
Widget
>[
const
Padding
(
padding:
EdgeInsets
.
only
(
right:
2
),
child:
TypingIndicator
(),
),
Text
(
user
.
getFullName
(),
style:
const
TextStyle
(
fontSize:
12
,
fontWeight:
FontWeight
.
bold
,
),
),
Text
(
'
$text
'
,
style:
const
TextStyle
(
fontSize:
12
),
),
],
),
);
}
}
lib/package/chat_dash/src/widgets/typing_users/typing_indicator.dart
0 → 100644
View file @
c7740f49
part of
dash_chat_2
;
/// @nodoc
class
TypingIndicator
extends
StatefulWidget
{
const
TypingIndicator
({
Key
?
key
,
this
.
flashingCircleDarkColor
=
const
Color
(
0xFF333333
),
this
.
flashingCircleBrightColor
=
const
Color
(
0xFFaec1dd
),
})
:
super
(
key:
key
);
/// Dark color in the animation
final
Color
flashingCircleDarkColor
;
/// Light color in the animation
final
Color
flashingCircleBrightColor
;
@override
_TypingIndicatorState
createState
()
=>
_TypingIndicatorState
();
}
class
_TypingIndicatorState
extends
State
<
TypingIndicator
>
with
TickerProviderStateMixin
{
late
AnimationController
_repeatingController
;
final
List
<
Interval
>
_dotIntervals
=
const
<
Interval
>[
Interval
(
0.25
,
0.8
),
Interval
(
0.35
,
0.9
),
Interval
(
0.45
,
1.0
),
];
@override
void
initState
()
{
super
.
initState
();
_repeatingController
=
AnimationController
(
vsync:
this
,
duration:
const
Duration
(
milliseconds:
1200
),
);
_repeatingController
.
repeat
();
}
@override
void
dispose
()
{
_repeatingController
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
SizedBox
(
width:
30
,
height:
15
,
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceEvenly
,
children:
<
Widget
>[
_buildFlashingCircle
(
0
),
_buildFlashingCircle
(
1
),
_buildFlashingCircle
(
2
),
],
),
);
}
Widget
_buildFlashingCircle
(
int
index
)
{
return
AnimatedBuilder
(
animation:
_repeatingController
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
final
double
circleFlashPercent
=
_dotIntervals
[
index
].
transform
(
_repeatingController
.
value
);
final
double
circleColorPercent
=
sin
(
pi
*
circleFlashPercent
);
return
Container
(
width:
5
,
height:
5
,
decoration:
BoxDecoration
(
shape:
BoxShape
.
circle
,
color:
Color
.
lerp
(
widget
.
flashingCircleDarkColor
,
widget
.
flashingCircleBrightColor
,
circleColorPercent
),
),
);
},
);
}
}
lib/pages/application/controller.dart
View file @
c7740f49
import
'dart:async'
;
import
'package:vibration/vibration.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
...
...
@@ -33,7 +33,10 @@ class ApplicationController extends GetxController {
/// 事件
// tab栏动画
void
handleNavBarTap
(
int
index
)
{
void
handleNavBarTap
(
int
index
)
async
{
// if (await Vibration.hasVibrator() != null) {
// Vibration.vibrate(duration: 10, amplitude: 128);
// }
pageController
.
animateToPage
(
index
,
duration:
const
Duration
(
milliseconds:
200
),
curve:
Curves
.
ease
);
}
...
...
lib/pages/frame/notfound/controller.dart
View file @
c7740f49
import
'package:chart/common/apis/apis.dart'
;
import
'package:chart/common/store/store.dart'
;
import
'package:
dash_chat_2/dash_chat_2.dart'
;
import
'package:
chart/package/chat_dash/dash_chat_2.dart'
as
Chat
;
import
'package:flutter_easyloading/flutter_easyloading.dart'
;
import
'package:get/get.dart'
;
import
'package:uuid/uuid.dart'
;
...
...
@@ -22,13 +22,13 @@ class ChatNewController extends GetxController {
// id: '82091008-a4aa-4a89-ae75-a22bf8d6f3aa',
// );
Chat
User
_user
=
ChatUser
(
Chat
.
ChatUser
_user
=
Chat
.
ChatUser
(
id:
'1'
,
// firstName: 'Charles',
// lastName: 'Leclerc',
);
final
receiveUser
=
ChatUser
(
final
receiveUser
=
Chat
.
Chat
User
(
id:
'82091008-a484-4a89-ae75-a22bf8d6f3aa'
,
firstName:
"GPT"
,
lastName:
'大师'
,
...
...
@@ -39,7 +39,7 @@ class ChatNewController extends GetxController {
/// 事件
void
sendMessage
(
ChatMessage
message
)
async
{
void
sendMessage
(
Chat
.
Chat
Message
message
)
async
{
// if (state.messageList.isNotEmpty) {
// // data = !_messages.every((element) => element.status != Status.sending);
// }
...
...
@@ -56,7 +56,7 @@ class ChatNewController extends GetxController {
// return;
// }
final
textMessage
=
ChatMessage
(
final
textMessage
=
Chat
.
Chat
Message
(
user:
_user
,
createdAt:
DateTime
.
now
(),
// id: const Uuid().v4(),
...
...
@@ -75,14 +75,14 @@ class ChatNewController extends GetxController {
_addMessage
(
textMessage
);
// _addMessage(loadingMessage);
EasyLoading
.
show
Progress
(
0.5
,
status:
"正在思考中
"
);
EasyLoading
.
show
(
status:
"正在思考中...
"
);
// ("正在思考中...");
try
{
String
?
result
=
await
NewsAPI
.
sendMessage
(
{
"question"
:
message
.
text
,
"id"
:
"
${UserStore.to.profile.id}
"
});
// _cancelLoading();
final
receiveMessage
=
ChatMessage
(
final
receiveMessage
=
Chat
.
Chat
Message
(
user:
receiveUser
,
createdAt:
DateTime
.
now
(),
// id: const Uuid().v4(),
...
...
@@ -93,7 +93,7 @@ class ChatNewController extends GetxController {
}
catch
(
e
)
{
print
(
"eeeeeeee
$e
"
);
// _cancelLoading();
final
receiveErrorMessage
=
ChatMessage
(
final
receiveErrorMessage
=
Chat
.
Chat
Message
(
user:
receiveUser
,
createdAt:
DateTime
.
now
(),
// id: const Uuid().v4(),
...
...
@@ -105,7 +105,7 @@ class ChatNewController extends GetxController {
}
}
void
_addMessage
(
ChatMessage
message
)
{
void
_addMessage
(
Chat
.
Chat
Message
message
)
{
state
.
messageList
.
insert
(
0
,
message
);
// state.messageList = [message]
// state.messageList.add(message);
...
...
lib/pages/frame/notfound/state.dart
View file @
c7740f49
// import 'dart:ffi';
import
'package:chart/common/entities/entities.dart'
;
import
'package:
dash_chat_2/dash_chat_2.dart'
;
import
'package:
chart/package/chat_dash/dash_chat_2.dart'
as
Chat
;
import
'package:get/get.dart'
;
import
'package:flutter_chat_types/flutter_chat_types.dart'
as
types
;
class
ChatPageState
{
// 新闻翻页 // List<types.Message>
RxList
<
Chat
Message
>
messageList
=
<
ChatMessage
>[].
obs
;
RxList
<
Chat
.
ChatMessage
>
messageList
=
<
Chat
.
ChatMessage
>[].
obs
;
// get _messageList =>
final
_page
=
"
hello
"
.
obs
;
final
_page
=
"
与人工智能机器人的对话
"
.
obs
;
set
page
(
value
)
=>
this
.
_page
.
value
=
value
;
get
page
=>
this
.
_page
.
value
;
// RxList<NewsItem> newsList = <NewsItem>[].obs;
...
...
lib/pages/frame/notfound/view.dart
View file @
c7740f49
import
'package:chart/common/routers/routes.dart'
;
import
'package:chart/common/values/values.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_chat_ui/flutter_chat_ui.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:get/get.dart'
;
import
'package:flutter_chat_types/flutter_chat_types.dart'
as
types
;
import
'../../../common/widgets/app.dart'
;
import
'../../application/view.dart'
;
import
'package:dash_chat_2/dash_chat_2.dart'
;
import
'index.dart'
;
import
'package:chart/package/chat_dash/dash_chat_2.dart'
as
Chat
;
import
'widgets/widgets.dart'
;
class
ChatNewPage
extends
GetView
<
ChatNewController
>
{
...
...
@@ -21,11 +21,12 @@ class ChatNewPage extends GetView<ChatNewController> {
@override
Widget
build
(
BuildContext
context
)
{
// final c = Get.put(ChatPageController());
final
c
=
Get
.
put
(
ChatNewController
());
// final c = Get.put(ChatNewController());
return
Obx
(()
=>
Scaffold
(
appBar:
transparentAppBar
(
title:
Text
(
"
${c.state.messageList.length}
"
,
"
${c
ontroller.state.page}${controller
.state.messageList.length}
"
,
style:
TextStyle
(
color:
AppColors
.
primaryElementText
,
fontFamily:
'Montserrat'
,
...
...
@@ -51,17 +52,95 @@ class ChatNewPage extends GetView<ChatNewController> {
body:
Container
(
width:
double
.
infinity
,
height:
double
.
infinity
,
padding:
EdgeInsets
.
symmetric
(
horizontal:
0
),
//
padding: EdgeInsets.symmetric(horizontal: 0),
decoration:
BoxDecoration
(
// rgba(36, 40, 64, 1.00)
// color: Color.fromRGBO(36, 40, 64, 1.00),
image:
DecorationImage
(
image:
Image
.
asset
(
"assets/images/bg.png"
).
image
,
fit:
BoxFit
.
cover
),
),
child:
DashChat
(
child:
Chat
.
DashChat
(
inputOptions:
const
Chat
.
InputOptions
(
// alwaysShowSend: true,
// sendButtonBuilder: (send) => const Text("data"),
// showTraillingBeforeSend: true,
inputTextStyle:
TextStyle
(
color:
Colors
.
white
),
inputToolbarStyle:
BoxDecoration
(
color:
Color
.
fromRGBO
(
36
,
40
,
64
,
1.00
),
//
// color: LinearGradient(
// width: 5,
// colors: [Colors.red, Colors.yellow],
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// ),
// Color.fromRGBO(36, 40, 64, 1.00),
// border: Border.all(
// width: 5,
// color: LinearGradient(
// colors: [Colors.red, Colors.yellow],
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// ),
// ),
// c
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
16
),
topRight:
Radius
.
circular
(
16
)),
),
inputToolbarMargin:
EdgeInsets
.
all
(
0
),
sendButtonBuilder:
null
,
inputToolbarPadding:
// symmetric(horizontal: 10, vertical: 20)
EdgeInsets
.
only
(
top:
15
,
right:
15
,
left:
15
,
bottom:
35
),
// inputToolbarPadding : const EdgeInsets.all(8.0),
// this.inputToolbarMargin = const EdgeInsets.only(top: 8.0),
// textController:
// sendButtonBuilder:
// () => TextButton(
// child: const Text("13213"),
// onPressed: (send) => {send()},
// )
// inputTextStyle: TextStyle(color: Colors.red),
// inputDecoration: InputDecoration(
// isDense: true,
// filled: true,
// fillColor: Colors.red,
// // contentPadding: const EdgeInsets.only(
// // left: 18,
// // top: 10,
// // bottom: 10,
// // ),
// // border: OutlineInputBorder(
// // borderRadius: BorderRadius.circular(25),
// // borderSide: const BorderSide(
// // width: 0,
// // style: BorderStyle.none,
// // ),
// // ),
// ),
),
currentUser:
_user
,
onSend:
c
.
sendMessage
,
messages:
c
.
state
.
messageList
,
onSend:
controller
.
sendMessage
,
// messageListOptions:
// const MessageListOptions(loadEarlierBuilder: Text("2131")),
messages:
controller
.
state
.
messageList
,
// messageListOptions: MessageListOptions(
// chatFooterBuilder: Container(
// color: Colors.red,
// width: double.infinity,
// height: 100.00,
// child: Text("footer")),
// ),
messageOptions:
Chat
.
MessageOptions
(
// containerColor: Colors.black,
),
),
// Column(children: [
// ]),
...
...
@@ -98,7 +177,7 @@ class ChatNewPage extends GetView<ChatNewController> {
}
}
Chat
User
_user
=
ChatUser
(
Chat
.
ChatUser
_user
=
Chat
.
ChatUser
(
id:
'1'
,
// firstName: 'Charles',
// lastName: 'Leclerc',
...
...
lib/pages/frame/product/controller.dart
View file @
c7740f49
...
...
@@ -3,6 +3,7 @@ import 'package:chart/common/store/user.dart';
// import 'package:flutter/cupertino.dart';
import
'package:flutter/material.dart'
;
import
'package:flutter_easyloading/flutter_easyloading.dart'
;
import
'package:get/get_connect/http/src/utils/utils.dart'
;
import
'package:share_plus/share_plus.dart'
;
import
'package:get/get.dart'
;
...
...
@@ -19,6 +20,7 @@ class ProductController extends GetxController {
TextEditingController
controller1
=
TextEditingController
();
TextEditingController
controller2
=
TextEditingController
();
ScrollController
_scrollController
=
ScrollController
();
/// 成员变量
...
...
@@ -70,6 +72,8 @@ class ProductController extends GetxController {
void
handleGenText
()
async
{
final
params
=
Get
.
parameters
;
// detailId
if
(
controller1
.
text
.
isNotEmpty
)
{
// 包含${controller2.text}的${params['title']}
String
str
=
"帮我写一篇
${params['firstLabel']}
是
${controller1.text}
"
;
...
...
@@ -80,15 +84,40 @@ class ProductController extends GetxController {
String
str3
=
"的
${params['title']}
"
;
print
(
str
+
str1
+
str3
);
// return
try
{
// GetX.pop.pop()
Get
.
back
();
state
.
loading
=
true
;
EasyLoading
.
show
(
status:
"AI正在生成中。。。"
);
String
result
=
await
NewsAPI
.
sendMessage
({
"question"
:
str
+
str1
+
str3
,
"id"
:
"
${UserStore.to.profile.id}
"
});
EasyLoading
.
show
(
status:
"AI正在生成中..."
);
// "question": str + str1 + str3, "id": "${UserStore.to.profile.id}
// [
// {
// "id": 0,
// "label": "",
// "placeHolder": "",
// "value": ""
// }
// ]
// json.encode(map);
String
result
=
await
NewsAPI
.
sendMessageByDetailId
([
{
"label"
:
params
[
'firstLabel'
],
"value"
:
controller1
.
text
,
"placeHolder"
:
params
[
'firstValue'
],
"sort"
:
1
,
},
{
"label"
:
params
[
'lastLabel'
],
"value"
:
controller2
.
text
,
"placeHolder"
:
params
[
'lastValue'
],
"sort"
:
2
,
}
],
params
[
'detailId'
]!);
// state.genText = result;
state
.
messageQueenItemQueen
.
add
(
MessageQueenItem
(
...
...
@@ -102,7 +131,7 @@ class ProductController extends GetxController {
state
.
loading
=
false
;
}
//
print("$str");
print
(
"
$str
"
);
}
else
{
Get
.
snackbar
(
"错误提示"
,
"您的问题还没有填完"
,
colorText:
Colors
.
white
);
}
...
...
@@ -124,7 +153,9 @@ class ProductController extends GetxController {
print
(
"awaitawaitawaitawaitawaitawaitawait"
);
// Share.share('Text I wish to share');
Get
.
bottomSheet
(
FormWidget
());
Get
.
bottomSheet
(
FormWidget
(),
);
// useRootNavigator: false,
// // backgroundColor: Colors.white,
// shape: const RoundedRectangleBorder(
...
...
@@ -141,7 +172,7 @@ class ProductController extends GetxController {
String
str
=
a
+
'
\n\n
'
+
"继续"
;
state
.
loading
=
true
;
EasyLoading
.
show
(
status:
"AI正在生成中
。。。
"
);
EasyLoading
.
show
(
status:
"AI正在生成中
...
"
);
String
result
=
await
NewsAPI
.
sendMessage
(
{
"question"
:
str
,
"id"
:
"
${UserStore.to.profile.id}
"
});
state
.
loading
=
false
;
...
...
lib/pages/frame/product/view.dart
View file @
c7740f49
...
...
@@ -161,18 +161,20 @@ class ProductPage extends GetView<ProductController> {
"
${idx.text}
"
,
speed:
const
Duration
(
milliseconds:
100
),
textStyle:
TextStyle
(
fontSize:
18
,
color:
Colors
.
white
,
fontWeight:
FontWeight
.
bold
),
fontSize:
18
,
color:
Colors
.
white
,
// fontWeight: FontWeight.bold
),
)
],
)
:
Text
(
"
${idx.text}
"
,
style:
TextStyle
(
fontSize:
18
,
color:
Colors
.
white
,
fontWeight:
FontWeight
.
bold
),
fontSize:
18
,
color:
Colors
.
white
,
// fontWeight: FontWeight.bold
),
);
return
text
;
...
...
lib/pages/main/controller.dart
View file @
c7740f49
...
...
@@ -49,11 +49,12 @@ class MainController extends GetxController {
asyncLoadBannerData
()
async
{
final
token
=
StorageService
.
to
.
getString
(
STORAGE_USER_TOKEN_KEY
);
// if (token.isEmpty) {
IntegralEntity
userInfo
=
await
UserAPI
.
getUserIntegral
();
await
UserStore
.
to
.
getUserInfo
(
userInfo
);
// }
// await UserStore.to.setToken('');
// (res.token);
if
(
token
.
isEmpty
)
{
IntegralEntity
userInfo
=
await
UserAPI
.
getUserIntegral
();
await
UserStore
.
to
.
getUserInfo
(
userInfo
);
}
List
<
MessageEntity
>?
list
=
await
NewsAPI
.
bannerList
();
...
...
lib/pages/main/widgets/banner.dart
View file @
c7740f49
...
...
@@ -85,12 +85,20 @@ class BannerPageWidget extends GetView<MainController> {
width:
300
,
height:
130
,
padding:
EdgeInsets
.
only
(
top:
16
),
child:
Image
.
asset
(
doctorsList
[
index
].
image
,
child:
Image
.
network
(
'
${controller.state.bannerPage![index].icon}
'
,
fit:
BoxFit
.
contain
,
width:
double
.
infinity
,
height:
double
.
infinity
,
//
height: double.infinity,
),
// controller.state.bannerPage![index]
// .classifyDesc,
// Image.asset(
// doctorsList[index].image,
// fit: BoxFit.contain,
// width: double.infinity,
// height: double.infinity,
// ),
),
],
),
...
...
lib/pages/main/widgets/categories.dart
View file @
c7740f49
...
...
@@ -13,6 +13,7 @@ class NewsCategoriesWidget extends GetView<MainController> {
@override
Widget
build
(
BuildContext
context
)
{
final
userC
=
Get
.
put
(
UserStore
());
return
Obx
(()
=>
controller
.
state
.
bannerList
==
null
?
Container
()
:
Container
(
...
...
@@ -30,14 +31,14 @@ class NewsCategoriesWidget extends GetView<MainController> {
// ignore: prefer_const_literals_to_create_immutables
children:
[
// ignore: prefer_const_constructors
Text
(
"Hi,
${UserStore.to
.profile.username}
"
,
// ignore: prefer_const_constructors
style:
TextStyle
(
color:
Colors
.
white
,
fontWeight:
FontWeight
.
w800
,
fontSize:
20
.
sp
),
),
Obx
(()
=>
Text
(
"Hi,
${userC
.profile.username}
"
,
// ignore: prefer_const_constructors
style:
TextStyle
(
color:
Colors
.
white
,
fontWeight:
FontWeight
.
w800
,
fontSize:
20
.
sp
),
)
),
SizedBox
(
height:
30
),
// ignore: prefer_const_constructors
Text
(
...
...
lib/pages/main/widgets/constants.dart
View file @
c7740f49
...
...
@@ -8,6 +8,18 @@ const kPrimarylightColor = Color(0xff77E2FE);
const
kBackgroundColor
=
Color
(
0xffEFF2F7
);
const
List
<
Color
>
kCategoriesPrimaryColor
=
[
Color
(
0xffFFCA8C
),
Color
(
0xff5DF9D3
),
Color
(
0xFF85E4FD
),
Color
(
0xffB8ACFF
),
Color
(
0xffFFCA8C
),
Color
(
0xff5DF9D3
),
Color
(
0xFF85E4FD
),
Color
(
0xffB8ACFF
),
Color
(
0xffFFCA8C
),
Color
(
0xff5DF9D3
),
Color
(
0xFF85E4FD
),
Color
(
0xffB8ACFF
),
Color
(
0xffFFCA8C
),
Color
(
0xff5DF9D3
),
Color
(
0xFF85E4FD
),
...
...
@@ -15,6 +27,22 @@ const List<Color> kCategoriesPrimaryColor = [
];
const
List
<
Color
>
kCategoriesSecondryColor
=
[
Color
(
0xffFEA741
),
Color
(
0xff31DFB5
),
Color
(
0xff45BAFB
),
Color
(
0xff9182F9
),
Color
(
0xffFEA741
),
Color
(
0xff31DFB5
),
Color
(
0xff45BAFB
),
Color
(
0xff9182F9
),
Color
(
0xffFEA741
),
Color
(
0xff31DFB5
),
Color
(
0xff45BAFB
),
Color
(
0xff9182F9
),
Color
(
0xffFEA741
),
Color
(
0xff31DFB5
),
Color
(
0xff45BAFB
),
Color
(
0xff9182F9
),
Color
(
0xffFEA741
),
Color
(
0xff31DFB5
),
Color
(
0xff45BAFB
),
...
...
lib/pages/main/widgets/list.dart
View file @
c7740f49
...
...
@@ -159,7 +159,7 @@ class ListPageWidget extends GetView<MainController> {
child:
Text
(
"使用模版"
),
onPressed:
()
async
{
// await Get.put(ProductController());
// final a = ;
var
firstLabel
=
controller
.
state
.
bannerPageDetail
![
index
]
...
...
@@ -183,13 +183,17 @@ class ListPageWidget extends GetView<MainController> {
var
title
=
controller
.
state
.
bannerPageDetail
![
index
].
detailName
;
var
detailId
=
'
${controller.state.bannerPageDetail![index].id}
'
;
Get
.
toNamed
(
AppRoutes
.
PRODUCT_PAGE
,
parameters:
{
"title"
:
title
,
"firstValue"
:
firstValue
,
"firstLabel"
:
firstLabel
,
"lastValue"
:
lastValue
,
"lastLabel"
:
lastLabel
"lastLabel"
:
lastLabel
,
"detailId"
:
detailId
});
Future
.
delayed
(
Duration
(
milliseconds:
100
),
()
{
...
...
@@ -245,24 +249,25 @@ class ListPageWidget extends GetView<MainController> {
child:
Row
(
children:
[
Container
(
padding:
EdgeInsets
.
all
(
14
),
decoration:
BoxDecoration
(
gradient:
LinearGradient
(
begin:
Alignment
.
topLeft
,
end:
Alignment
.
bottomRight
,
colors:
[
kCategoriesPrimaryColor
[
index
],
kCategoriesSecondryColor
[
index
],
],
),
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Icon
(
Icons
.
headset_mic
,
size:
20
,
color:
Colors
.
white
,
),
),
padding:
EdgeInsets
.
all
(
10
),
decoration:
BoxDecoration
(
gradient:
LinearGradient
(
begin:
Alignment
.
topLeft
,
end:
Alignment
.
bottomRight
,
colors:
[
kCategoriesPrimaryColor
[
index
],
kCategoriesSecondryColor
[
index
],
],
),
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Image
.
network
(
'
${controller.state.bannerPageDetail![index].icon}
'
,
// "https://cdn-icons-png.flaticon.com/128/6784/6784128.png",
fit:
BoxFit
.
cover
,
width:
30.0
,
height:
30.0
,
)),
SizedBox
(
width:
11
),
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
...
...
lib/pages/main/widgets/swiper.dart
View file @
c7740f49
import
'package:chart/common/routers/routes.dart'
;
import
'package:chart/entity/plan_entity.dart'
;
import
'package:chart/pages/frame/notfound/index.dart'
;
import
'package:
dash_chat_2/dash_chat_2.dart'
;
import
'package:
chart/package/chat_dash/dash_chat_2.dart'
as
Chat
;
import
'package:flutter/material.dart'
;
import
'package:chart/common/values/values.dart'
;
import
'package:flutter_chat_types/flutter_chat_types.dart'
;
...
...
@@ -101,7 +101,7 @@ class SiperBannerWidget extends GetView<MainController> {
child:
InkWell
(
onTap:
()
{
// message.question
Chat
User
_user
=
ChatUser
(
Chat
.
ChatUser
_user
=
Chat
.
ChatUser
(
id:
'1'
,
// firstName: 'Charles',
// lastName: 'Leclerc',
...
...
@@ -110,7 +110,7 @@ class SiperBannerWidget extends GetView<MainController> {
Get
.
toNamed
(
"
${AppRoutes.CHAT_PAGE}
?question=
${message.question}
"
);
c
.
sendMessage
(
ChatMessage
(
c
.
sendMessage
(
Chat
.
Chat
Message
(
text:
"
${message.question}
"
,
user:
_user
,
createdAt:
DateTime
.
now
(),
...
...
lib/pages/template/view.dart
View file @
c7740f49
import
'package:chart/common/values/values.dart'
;
import
'package:chart/common/widgets/widgets.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get_connect/sockets/src/socket_notifier.dart'
;
import
'package:glassmorphism/glassmorphism.dart'
;
import
'index.dart'
;
import
'widgets/widgets.dart'
;
...
...
@@ -11,7 +13,47 @@ class TemplatePage extends GetView<TemplateController> {
// 主视图
Widget
_buildView
()
{
return
const
HelloWidget
();
return
Container
(
height:
double
.
infinity
,
width:
double
.
infinity
,
decoration:
BoxDecoration
(
image:
DecorationImage
(
image:
Image
.
asset
(
"assets/images/bg.png"
).
image
,
fit:
BoxFit
.
cover
),
),
child:
const
HelloWidget
(),
// GlassmorphicContainer(
// width: Get.mediaQuery.size.width * 1,
// height: Get.mediaQuery.size.height * 1,
// // margin: EdgeInsets.only(bottom: 60),
// // padding: EdgeInsets.all(20),
// // ignore: sort_child_properties_last
// child:
// borderRadius: 14,
// blur: 14,
// alignment: Alignment.bottomCenter,
// border: 2,
// linearGradient: LinearGradient(
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// colors: [
// const Color(0xFF0FFFF).withOpacity(0.0),
// const Color(0xFF0FFFF).withOpacity(0.0),
// ],
// ),
// borderGradient: LinearGradient(
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// colors: [
// const Color(0xFF0FFFF).withOpacity(1),
// const Color(0xFFFFFFF),
// const Color(0xFF0FFFF).withOpacity(1),
// ],
// ),
// // child: ,
// ),
);
}
@override
...
...
@@ -20,10 +62,28 @@ class TemplatePage extends GetView<TemplateController> {
builder:
(
_
)
{
return
Scaffold
(
appBar:
transparentAppBar
(
leading:
IconButton
(
tooltip:
'返回上一页'
,
icon:
const
Icon
(
Icons
.
arrow_back
,
color:
AppColors
.
primaryElementText
,
),
onPressed:
()
async
{
// Get.back();
// Get.offAll(ApplicationPage());
// await Get.off(ApplicationPage());
// Get.toNamed(AppRoutes.Application);
Get
.
back
();
// await Get.toNamed();
// Navigator.of(context).pop();
//_nextPage(-1);
},
),
title:
const
Text
(
"template
"
,
style:
TextStyle
(
color:
Colors
.
white
),
)),
"模版中心
"
,
style:
TextStyle
(
color:
Colors
.
white
),
)),
body:
_buildView
());
},
);
...
...
lib/pages/template/widgets/hello.dart
View file @
c7740f49
This diff is collapsed.
Click to expand it.
lib/pages/user/view.dart
View file @
c7740f49
import
'package:chart/common/store/user.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:babstrap_settings_screen/babstrap_settings_screen.dart'
;
...
...
@@ -6,6 +7,7 @@ import 'index.dart';
import
'widgets/widgets.dart'
;
class
UserDetailPage
extends
GetView
<
UserDetailController
>
{
final
c
=
Get
.
put
(
UserStore
());
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
...
...
@@ -78,19 +80,19 @@ class UserDetailPage extends GetView<UserDetailController> {
// textBaseline: TextBaseline.alphabetic,
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:
[
Container
(
height:
30
,
// color: Colors.white,
child:
Text
(
"一颗大白菜"
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
height:
1.5
,
fontWeight:
FontWeight
.
bold
),
),
margin:
EdgeInsets
.
only
(
right:
16
),
),
Obx
(()
=>
Container
(
height:
30
,
// color: Colors.white,
child:
Text
(
'
${c.profile.username}
'
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
16
,
height:
1.5
,
fontWeight:
FontWeight
.
bold
),
),
margin:
EdgeInsets
.
only
(
right:
16
),
)
),
Container
(
width:
60
,
height:
30
,
...
...
lib/pages1/chat/chat_page.dart
View file @
c7740f49
...
...
@@ -460,7 +460,7 @@ Widget _bubbleBuilder(Widget child,
totalRepeatCount:
1
,
animatedTexts:
identical
(
message
.
status
,
Status
.
sending
)
?
[
TypewriterAnimatedText
(
'正在思考中...
...
'
),
TypewriterAnimatedText
(
'正在思考中...'
),
TypewriterAnimatedText
(
'正在使劲思考中......'
),
TypewriterAnimatedText
(
'正在拼命思考中......'
),
TypewriterAnimatedText
(
'您的问题太有深度,请稍等......'
),
...
...
lib/pages1/home/home_page.dart
View file @
c7740f49
...
...
@@ -450,7 +450,7 @@ Widget _bubbleBuilder(
totalRepeatCount:
1
,
animatedTexts:
identical
(
message
.
status
,
Status
.
sending
)
?
[
WavyAnimatedText
(
'正在思考中...
...
'
),
WavyAnimatedText
(
'正在思考中...'
),
WavyAnimatedText
(
'正在使劲思考中......'
),
WavyAnimatedText
(
'正在拼命思考中......'
),
WavyAnimatedText
(
'您的问题太有深度,回答很困难,如果不想等待,请问下一个问题......'
),
...
...
pubspec.lock
View file @
c7740f49
...
...
@@ -560,6 +560,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.6"
gradient_borders:
dependency: "direct main"
description:
name: gradient_borders
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
gradient_widgets:
dependency: "direct main"
description:
...
...
@@ -1125,6 +1132,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
vibration:
dependency: "direct main"
description:
name: vibration
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.6"
video_player:
dependency: transitive
description:
...
...
pubspec.yaml
View file @
c7740f49
...
...
@@ -105,6 +105,8 @@ dependencies:
glassy
:
^0.0.6
dash_chat_2
:
^0.0.15
flutter_staggered_animations
:
^1.1.1
vibration
:
^1.7.6
gradient_borders
:
^1.0.0
# package:bubble/bubble.dart
dev_dependencies
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment