merge: merging pinned conversation updates to sse
commit
12350d23c9
|
@ -21,7 +21,7 @@ class ConversationBloc {
|
|||
|
||||
Observable<List<Conversation>> get pinnedConversations =>
|
||||
_conversationsFetcher.stream.map((conversationList) => conversationList
|
||||
.where((conversation) => conversation.pinned)
|
||||
.where((conversation) => conversation.pinned ?? false)
|
||||
.toList());
|
||||
|
||||
Observable<Conversation> getConversation(String id) =>
|
||||
|
|
|
@ -45,6 +45,19 @@ class ConversationApiProvider {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> pinConversation(String id) async {
|
||||
final jwt = await loginManager.getToken();
|
||||
try {
|
||||
await globalHttpClient
|
||||
.post("$baseUrlCore/user/conversation/$id/pin", headers: {
|
||||
HttpHeaders.contentTypeHeader: " application/json",
|
||||
HttpHeaders.authorizationHeader: "Bearer $jwt"
|
||||
});
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createConversationMember(
|
||||
String conversationId, String userId) async {
|
||||
final jwt = await loginManager.getToken();
|
||||
|
|
|
@ -1,33 +1,52 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
import "../../widgets/image_avatar.dart";
|
||||
import "../../../models/user_model.dart";
|
||||
import "../../../models/conversation_model.dart";
|
||||
import "../../../blocs/conversation_bloc.dart";
|
||||
|
||||
class ConversationInactiveView extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _ConversationInactiveViewState();
|
||||
}
|
||||
}
|
||||
|
||||
class _ConversationInactiveViewState extends State<ConversationInactiveView> {
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
conversationsBloc.fetchConversations();
|
||||
}
|
||||
|
||||
class ConversationInactiveView extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
ImageAvatar(
|
||||
radius: 18,
|
||||
padding: EdgeInsets.only(right: 5.0),
|
||||
info: ImageAvatarInfo.fromUser(
|
||||
User("1", "Isaac", "Tay", "+65 91043593", "", "", ""))),
|
||||
ImageAvatar(
|
||||
radius: 18,
|
||||
padding: EdgeInsets.only(right: 5.0),
|
||||
info: ImageAvatarInfo.fromUser(
|
||||
User("1", "Isaac", "Tay", "+65 91043593", "", "", ""))),
|
||||
ImageAvatar(
|
||||
radius: 18,
|
||||
padding: EdgeInsets.only(right: 5.0),
|
||||
info: ImageAvatarInfo.fromUser(
|
||||
User("1", "Isaac", "Tay", "+65 91043593", "", "", "")))
|
||||
])
|
||||
StreamBuilder(
|
||||
stream: conversationsBloc.pinnedConversations,
|
||||
builder: (context, AsyncSnapshot<List<Conversation>> snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: (snapshot.data.length < 1)
|
||||
? <Widget>[
|
||||
Spacer(),
|
||||
Text("No pinned conversations :("),
|
||||
Spacer()
|
||||
]
|
||||
: snapshot.data
|
||||
.map((conversation) => ImageAvatar(
|
||||
radius: 18,
|
||||
padding: EdgeInsets.only(right: 5.0),
|
||||
info: ImageAvatarInfo.fromConversation(
|
||||
conversation)))
|
||||
.toList());
|
||||
} else if (snapshot.hasError) {
|
||||
return Text(snapshot.error.toString());
|
||||
}
|
||||
return Center(child: CircularProgressIndicator());
|
||||
})
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import "../blocs/message_bloc.dart";
|
|||
|
||||
import "./conversation_tab/conversation_tab.dart";
|
||||
import "./contact_tab/contact_tab.dart";
|
||||
import './settings_tab/settings_tab.dart';
|
||||
import "./bottom_bar/bottom_bar.dart";
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
|
@ -89,7 +90,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
|||
children: <Widget>[
|
||||
ContactTab(),
|
||||
ConversationTab(),
|
||||
Container(),
|
||||
SettingsTab(),
|
||||
]),
|
||||
bottomNavigationBar:
|
||||
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import "package:flutter/material.dart";
|
||||
import 'package:frontend_flutter/src/ui/settings_tab/widgets/data_usage_view.dart';
|
||||
import 'package:frontend_flutter/src/ui/settings_tab/widgets/interface_view.dart';
|
||||
import 'package:frontend_flutter/src/ui/settings_tab/widgets/notifications_view.dart';
|
||||
import 'package:frontend_flutter/src/ui/settings_tab/widgets/privacy_security_view.dart';
|
||||
import 'package:frontend_flutter/src/ui/widgets/top_bar.dart';
|
||||
|
||||
import "./widgets/home_view.dart";
|
||||
|
||||
class SettingsTab extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _SettingsTabState();
|
||||
}
|
||||
}
|
||||
|
||||
class _SettingsTabState extends State<SettingsTab> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Navigator(
|
||||
initialRoute: "settings/home",
|
||||
onGenerateRoute: (RouteSettings settings) {
|
||||
WidgetBuilder builder;
|
||||
switch (settings.name) {
|
||||
case "settings/home":
|
||||
builder = (BuildContext _) => HomeView();
|
||||
break;
|
||||
case "settings/interface":
|
||||
builder = (BuildContext _) => InterfaceView();
|
||||
break;
|
||||
case "settings/notifications":
|
||||
builder = (BuildContext _) => NotificationsView();
|
||||
break;
|
||||
case "settings/privacy_security":
|
||||
builder = (BuildContext _) => PrivacySecurityView();
|
||||
break;
|
||||
case "settings/data_usage":
|
||||
builder = (BuildContext _) => DataUsageView();
|
||||
break;
|
||||
// case "settings/new/groupinfo":
|
||||
// final List<User> users = settings.arguments;
|
||||
// builder = (BuildContext _) => NewGroupInfoView(users: users);
|
||||
// break;
|
||||
default:
|
||||
throw Exception("Invalid route: ${settings.name}");
|
||||
}
|
||||
return MaterialPageRoute(builder: builder, settings: settings);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
import "../../widgets/top_bar.dart";
|
||||
import "../../widgets/list_button.dart";
|
||||
|
||||
class DataUsageView extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _DataUsageViewState();
|
||||
}
|
||||
}
|
||||
|
||||
class _DataUsageViewState extends State<DataUsageView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
TopBar(
|
||||
title: "Data Usage",
|
||||
children: <Widget>[
|
||||
BackButton(),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Text('Data Usage View'),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
import 'dart:async' show Future;
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import 'package:frontend_flutter/src/ui/widgets/image_avatar.dart';
|
||||
|
||||
import "../../widgets/top_bar.dart";
|
||||
import "../../widgets/list_button.dart";
|
||||
|
||||
class HomeView extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _HomeViewState();
|
||||
}
|
||||
}
|
||||
|
||||
class _HomeViewState extends State<HomeView> {
|
||||
final _textFieldController = TextEditingController();
|
||||
String name = 'Daniel Lim Hai';
|
||||
String bio = 'Hey there, I am using Meep!';
|
||||
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
dispose() {
|
||||
super.dispose();
|
||||
_textFieldController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _titleTheme = Theme.of(context)
|
||||
.textTheme
|
||||
.title
|
||||
.copyWith(color: Theme.of(context).accentColor);
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
TopBar(
|
||||
title: "Settings",
|
||||
children: <Widget>[
|
||||
Visibility(
|
||||
child: BackButton(),
|
||||
maintainSize: true,
|
||||
maintainAnimation: true,
|
||||
maintainState: true,
|
||||
visible: false,
|
||||
),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Stack(
|
||||
children: <Widget>[
|
||||
Positioned(
|
||||
child: ImageAvatar(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
info: ImageAvatarInfo(lastName: 'Daniel'),
|
||||
radius: 70.0,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 115.0,
|
||||
left: 115.0,
|
||||
child: FloatingActionButton(
|
||||
backgroundColor: Theme.of(context).primaryColorDark,
|
||||
onPressed: () => {},
|
||||
mini: true,
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.only(top: 0.0),
|
||||
children: <Widget>[
|
||||
ListButton(
|
||||
icon: Icons.person,
|
||||
text: name,
|
||||
subtitle: 'Name',
|
||||
onClickCallback: () {
|
||||
_displayTextFieldDialog(
|
||||
context: context,
|
||||
title: 'Edit Name',
|
||||
existingText: name,
|
||||
hintText: 'Name',
|
||||
).then((text) {
|
||||
//TODO: Logic for changing name
|
||||
if (text != null) {
|
||||
setState(() {
|
||||
name = text;
|
||||
print(text);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
textStyle: _titleTheme,
|
||||
iconColor: Theme.of(context).primaryColorDark,
|
||||
),
|
||||
ListButton(
|
||||
icon: Icons.info,
|
||||
text: bio,
|
||||
subtitle: 'Bio',
|
||||
onClickCallback: () {
|
||||
_displayTextFieldDialog(
|
||||
context: context,
|
||||
title: 'Edit Bio',
|
||||
existingText: bio,
|
||||
hintText: 'Bio',
|
||||
).then((text) {
|
||||
//TODO: Logic for changing bio
|
||||
if (text != null) {
|
||||
setState(() {
|
||||
bio = text;
|
||||
print(text);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
textStyle: _titleTheme,
|
||||
iconColor: Theme.of(context).primaryColorDark,
|
||||
),
|
||||
Divider(),
|
||||
ListButton(
|
||||
icon: Icons.color_lens,
|
||||
text: 'Interface',
|
||||
onClickCallback: () {
|
||||
Navigator.of(context).pushNamed("settings/interface");
|
||||
},
|
||||
textStyle: _titleTheme,
|
||||
iconColor: Theme.of(context).primaryColorDark,
|
||||
),
|
||||
ListButton(
|
||||
icon: Icons.notifications,
|
||||
text: 'Notifications',
|
||||
onClickCallback: () {
|
||||
Navigator.of(context).pushNamed("settings/notifications");
|
||||
},
|
||||
textStyle: _titleTheme,
|
||||
iconColor: Theme.of(context).primaryColorDark,
|
||||
),
|
||||
ListButton(
|
||||
icon: Icons.security,
|
||||
text: 'Privacy and Security',
|
||||
onClickCallback: () {
|
||||
Navigator.of(context).pushNamed("settings/privacy_security");
|
||||
},
|
||||
textStyle: _titleTheme,
|
||||
iconColor: Theme.of(context).primaryColorDark,
|
||||
),
|
||||
ListButton(
|
||||
icon: Icons.data_usage,
|
||||
text: 'Data Usage',
|
||||
onClickCallback: () {
|
||||
Navigator.of(context).pushNamed("settings/data_usage");
|
||||
},
|
||||
textStyle: _titleTheme,
|
||||
iconColor: Theme.of(context).primaryColorDark,
|
||||
),
|
||||
Divider(),
|
||||
ListButton(
|
||||
icon: Icons.exit_to_app,
|
||||
text: 'Sign Out',
|
||||
onClickCallback: () {},
|
||||
textStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.title
|
||||
.copyWith(color: Colors.redAccent),
|
||||
iconColor: Colors.redAccent,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
_displayTextFieldDialog({
|
||||
@required BuildContext context,
|
||||
@required String title,
|
||||
String existingText,
|
||||
String hintText,
|
||||
}) async {
|
||||
_textFieldController.text = existingText;
|
||||
|
||||
// Introduce artificial delay so the button press animation can be seen
|
||||
await new Future.delayed(const Duration(milliseconds: 220));
|
||||
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.title,
|
||||
),
|
||||
content: TextField(
|
||||
controller: _textFieldController,
|
||||
decoration: InputDecoration(hintText: hintText),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: <Widget>[
|
||||
new FlatButton(
|
||||
child: new Text('Cancel'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
new FlatButton(
|
||||
child: new Text('Submit'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(_textFieldController.text);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import "package:flutter/material.dart";
|
||||
import 'package:frontend_flutter/src/ui/widgets/list_text_button.dart';
|
||||
|
||||
import "../../widgets/top_bar.dart";
|
||||
import "../../widgets/list_button.dart";
|
||||
|
||||
class InterfaceView extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _InterfaceViewState();
|
||||
}
|
||||
}
|
||||
|
||||
class _InterfaceViewState extends State<InterfaceView> {
|
||||
bool _enterToSend = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _buttonTextTheme = Theme.of(context)
|
||||
.textTheme
|
||||
.title
|
||||
.copyWith(color: Theme.of(context).accentColor);
|
||||
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
TopBar(
|
||||
title: "Interface",
|
||||
children: <Widget>[
|
||||
BackButton(),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.only(top: 0.0),
|
||||
children: <Widget>[
|
||||
SwitchListTile(
|
||||
title: Text('Enter to Send', style: _buttonTextTheme),
|
||||
value: _enterToSend,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
_enterToSend = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
ListTextButton(
|
||||
text: 'Font Size',
|
||||
subtitle: 'Medium',
|
||||
textStyle: _buttonTextTheme,
|
||||
onClickCallback: () {
|
||||
|
||||
},
|
||||
),
|
||||
ListTextButton(
|
||||
text: 'Wallpaper',
|
||||
textStyle: _buttonTextTheme,
|
||||
onClickCallback: () {
|
||||
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import "package:flutter/material.dart";
|
||||
import 'package:frontend_flutter/src/ui/widgets/list_text_button.dart';
|
||||
|
||||
import "../../widgets/top_bar.dart";
|
||||
|
||||
class NotificationsView extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _NotificationsViewState();
|
||||
}
|
||||
}
|
||||
|
||||
class _NotificationsViewState extends State<NotificationsView> {
|
||||
bool _inChatSounds = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _buttonTextTheme = Theme.of(context)
|
||||
.textTheme
|
||||
.title
|
||||
.copyWith(color: Theme.of(context).accentColor);
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
TopBar(
|
||||
title: "Notifications",
|
||||
children: <Widget>[
|
||||
BackButton(),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.only(top: 0.0),
|
||||
children: <Widget>[
|
||||
SwitchListTile(
|
||||
title: Text('In-Chat Sounds', style: _buttonTextTheme),
|
||||
value: _inChatSounds,
|
||||
onChanged: (bool value) {
|
||||
setState(() {
|
||||
_inChatSounds = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
ListTextButton(
|
||||
text: 'Notification Sound',
|
||||
subtitle: 'Default',
|
||||
textStyle: _buttonTextTheme,
|
||||
onClickCallback: () {
|
||||
|
||||
},
|
||||
),
|
||||
ListTextButton(
|
||||
text: 'Vibrate',
|
||||
subtitle: 'Default',
|
||||
textStyle: _buttonTextTheme,
|
||||
onClickCallback: () {
|
||||
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
import "../../widgets/top_bar.dart";
|
||||
import "../../widgets/list_button.dart";
|
||||
|
||||
class PrivacySecurityView extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return _PrivacySecurityViewState();
|
||||
}
|
||||
}
|
||||
|
||||
class _PrivacySecurityViewState extends State<PrivacySecurityView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
TopBar(
|
||||
title: "Privacy and Security",
|
||||
children: <Widget>[
|
||||
BackButton(),
|
||||
Spacer(),
|
||||
],
|
||||
),
|
||||
Text('Privacy and Security View'),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -142,7 +142,12 @@ class _ConversationItemState extends State<ConversationItem> {
|
|||
// onTap: () => print('Pin'))],
|
||||
secondaryActions: <Widget>[
|
||||
IconSlideAction(
|
||||
color: Colors.green, icon: Icons.star, onTap: () => print('Pin')),
|
||||
color: Colors.green,
|
||||
icon: Icons.star,
|
||||
onTap: () async {
|
||||
await conversationApiProvider
|
||||
.pinConversation(widget.conversation.id);
|
||||
}),
|
||||
IconSlideAction(
|
||||
color: Colors.red,
|
||||
icon: Icons.delete,
|
||||
|
|
|
@ -6,11 +6,19 @@ class ListButton extends StatelessWidget {
|
|||
final IconData icon;
|
||||
final String text;
|
||||
final OnClickCallback onClickCallback;
|
||||
final String subtitle;
|
||||
final TextStyle textStyle;
|
||||
final TextStyle subtitleStyle;
|
||||
final Color iconColor;
|
||||
|
||||
ListButton(
|
||||
{@required this.icon,
|
||||
@required this.text,
|
||||
@required this.onClickCallback});
|
||||
@required this.onClickCallback,
|
||||
this.subtitle,
|
||||
this.textStyle,
|
||||
this.subtitleStyle,
|
||||
this.iconColor});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -27,12 +35,33 @@ class ListButton extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
Icon(icon,
|
||||
size: 30.0,
|
||||
color: Theme.of(context).primaryColorDark),
|
||||
color:
|
||||
iconColor ?? Theme.of(context).primaryColorDark),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20.0),
|
||||
child: Text(text,
|
||||
style: Theme.of(context).textTheme.title.copyWith(
|
||||
color: Theme.of(context).primaryColorDark))),
|
||||
padding: EdgeInsets.only(left: 20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
text,
|
||||
style: textStyle ??
|
||||
Theme.of(context).textTheme.title.copyWith(
|
||||
color:
|
||||
Theme.of(context).primaryColorDark),
|
||||
),
|
||||
(subtitle == null)
|
||||
? Container()
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(top: 3.0),
|
||||
child: Text(
|
||||
subtitle,
|
||||
style: subtitleStyle ??
|
||||
Theme.of(context).textTheme.subtitle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
]))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import "package:flutter/material.dart";
|
||||
|
||||
typedef void OnClickCallback();
|
||||
|
||||
class ListTextButton extends StatelessWidget {
|
||||
final String text;
|
||||
final OnClickCallback onClickCallback;
|
||||
final String subtitle;
|
||||
final TextStyle textStyle;
|
||||
final TextStyle subtitleStyle;
|
||||
|
||||
ListTextButton({
|
||||
@required this.text,
|
||||
@required this.onClickCallback,
|
||||
this.subtitle,
|
||||
this.textStyle,
|
||||
this.subtitleStyle,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
elevation: 1,
|
||||
child: InkWell(
|
||||
onTap: onClickCallback,
|
||||
child: Container(
|
||||
height: (subtitle == null) ? 62.0 : null, // Default height if no subtitles
|
||||
padding:
|
||||
EdgeInsets.only(left: 15.0, right: 15.0, top: 12.0, bottom: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
text,
|
||||
style: textStyle ??
|
||||
Theme.of(context)
|
||||
.textTheme
|
||||
.title
|
||||
.copyWith(color: Theme.of(context).primaryColorDark),
|
||||
),
|
||||
(subtitle == null)
|
||||
? Container()
|
||||
: Padding(
|
||||
padding: EdgeInsets.only(top: 3.0),
|
||||
child: Text(
|
||||
subtitle,
|
||||
style: subtitleStyle ??
|
||||
Theme.of(context).textTheme.subtitle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue