design: Improve new design

This commit is contained in:
Christian Pauly 2021-02-03 15:47:51 +01:00
parent 82fe657e68
commit 692cb48aaf
12 changed files with 296 additions and 279 deletions

View File

@ -12,6 +12,7 @@ class ContentBanner extends StatelessWidget {
final bool loading; final bool loading;
final Function onEdit; final Function onEdit;
final Client client; final Client client;
final double opacity;
const ContentBanner(this.mxContent, const ContentBanner(this.mxContent,
{this.height = 400, {this.height = 400,
@ -19,6 +20,7 @@ class ContentBanner extends StatelessWidget {
this.loading = false, this.loading = false,
this.onEdit, this.onEdit,
this.client, this.client,
this.opacity = 0.75,
Key key}) Key key})
: super(key: key); : super(key: key);
@ -35,7 +37,7 @@ class ContentBanner extends StatelessWidget {
animated: true, animated: true,
); );
return Container( return Container(
height: 300, height: height,
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).secondaryHeaderColor, color: Theme.of(context).secondaryHeaderColor,
@ -48,7 +50,7 @@ class ContentBanner extends StatelessWidget {
top: 0, top: 0,
bottom: 0, bottom: 0,
child: Opacity( child: Opacity(
opacity: 0.75, opacity: opacity,
child: !loading child: !loading
? mxContent != null ? mxContent != null
? CachedNetworkImage( ? CachedNetworkImage(

View File

@ -16,7 +16,6 @@ import 'package:fluffychat/views/login.dart';
import 'package:fluffychat/views/new_group.dart'; import 'package:fluffychat/views/new_group.dart';
import 'package:fluffychat/views/new_private_chat.dart'; import 'package:fluffychat/views/new_private_chat.dart';
import 'package:fluffychat/views/set_status_view.dart'; import 'package:fluffychat/views/set_status_view.dart';
import 'package:fluffychat/views/settings.dart';
import 'package:fluffychat/views/settings_3pid.dart'; import 'package:fluffychat/views/settings_3pid.dart';
import 'package:fluffychat/views/settings_devices.dart'; import 'package:fluffychat/views/settings_devices.dart';
import 'package:fluffychat/views/settings_emotes.dart'; import 'package:fluffychat/views/settings_emotes.dart';
@ -149,17 +148,17 @@ class FluffyRoutes {
switch (action) { switch (action) {
case '3pid': case '3pid':
return ViewData( return ViewData(
leftView: (_) => Settings(), leftView: (_) => HomeView(),
mainView: (_) => Settings3Pid(), mainView: (_) => Settings3Pid(),
); );
case 'devices': case 'devices':
return ViewData( return ViewData(
leftView: (_) => Settings(), leftView: (_) => HomeView(),
mainView: (_) => DevicesSettings(), mainView: (_) => DevicesSettings(),
); );
case 'emotes': case 'emotes':
return ViewData( return ViewData(
leftView: (_) => Settings(), leftView: (_) => HomeView(),
mainView: (_) => EmotesSettings( mainView: (_) => EmotesSettings(
room: ((settings.arguments ?? {}) as Map)['room'], room: ((settings.arguments ?? {}) as Map)['room'],
stateKey: ((settings.arguments ?? {}) as Map)['stateKey'], stateKey: ((settings.arguments ?? {}) as Map)['stateKey'],
@ -167,25 +166,25 @@ class FluffyRoutes {
); );
case 'ignore': case 'ignore':
return ViewData( return ViewData(
leftView: (_) => Settings(), leftView: (_) => HomeView(),
mainView: (_) => SettingsIgnoreList( mainView: (_) => SettingsIgnoreList(
initialUserId: settings.arguments, initialUserId: settings.arguments,
), ),
); );
case 'notifications': case 'notifications':
return ViewData( return ViewData(
leftView: (_) => Settings(), leftView: (_) => HomeView(),
mainView: (_) => SettingsNotifications(), mainView: (_) => SettingsNotifications(),
); );
case 'style': case 'style':
return ViewData( return ViewData(
leftView: (_) => Settings(), leftView: (_) => HomeView(),
mainView: (_) => SettingsStyle(), mainView: (_) => SettingsStyle(),
); );
} }
} }
return ViewData( return ViewData(
mainView: (_) => Settings(), mainView: (_) => HomeView(),
emptyView: (_) => EmptyPage(), emptyView: (_) => EmptyPage(),
); );
} }

View File

@ -1025,8 +1025,13 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"newPrivateChat": "New private chat", "noStatusesFound": "No statuses found so far.",
"@newPrivateChat": { "@noStatusesFound": {
"type": "text",
"placeholders": {}
},
"newChat": "New chat",
"@newChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
@ -1352,6 +1357,16 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"contacts": "Contacts",
"@contacts": {
"type": "text",
"placeholders": {}
},
"all": "All",
"@all": {
"type": "text",
"placeholders": {}
},
"discover": "Discover", "discover": "Discover",
"@discover": { "@discover": {
"type": "text", "type": "text",

View File

@ -571,14 +571,14 @@ class _ChatState extends State<Chat> {
: Row( : Row(
children: <Widget>[ children: <Widget>[
Icon(Icons.edit_outlined, Icon(Icons.edit_outlined,
color: Theme.of(context).primaryColor, color: Theme.of(context).accentColor,
size: 13), size: 13),
SizedBox(width: 4), SizedBox(width: 4),
Text( Text(
room.getLocalizedTypingText(context), room.getLocalizedTypingText(context),
maxLines: 1, maxLines: 1,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).accentColor,
fontStyle: FontStyle.italic, fontStyle: FontStyle.italic,
fontSize: 16, fontSize: 16,
), ),

View File

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:adaptive_page_layout/adaptive_page_layout.dart';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:fluffychat/views/home_view_parts/discover.dart'; import 'package:fluffychat/views/home_view_parts/discover.dart';
import 'package:fluffychat/views/share_view.dart'; import 'package:fluffychat/views/share_view.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -11,12 +12,12 @@ import 'package:fluffychat/app_config.dart';
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:preload_page_view/preload_page_view.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import '../components/matrix.dart'; import '../components/matrix.dart';
import '../utils/matrix_file_extension.dart'; import '../utils/matrix_file_extension.dart';
import '../utils/url_launcher.dart'; import '../utils/url_launcher.dart';
import 'home_view_parts/chat_list.dart'; import 'home_view_parts/chat_list.dart';
import 'home_view_parts/settings.dart';
import 'home_view_parts/status_list.dart'; import 'home_view_parts/status_list.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
@ -31,13 +32,18 @@ class HomeView extends StatefulWidget {
_HomeViewState createState() => _HomeViewState(); _HomeViewState createState() => _HomeViewState();
} }
class _HomeViewState extends State<HomeView> { class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
@override @override
void initState() { void initState() {
_initReceiveSharingIntent(); _initReceiveSharingIntent();
_pageController = TabController(length: 4, vsync: this, initialIndex: 1);
_pageController.addListener(_updateCurrentIndex);
super.initState(); super.initState();
} }
void _updateCurrentIndex() =>
setState(() => currentIndex = _pageController.index);
int currentIndex = 1; int currentIndex = 1;
StreamSubscription _intentDataStreamSubscription; StreamSubscription _intentDataStreamSubscription;
@ -48,8 +54,7 @@ class _HomeViewState extends State<HomeView> {
AppBar appBar; AppBar appBar;
final PreloadPageController _pageController = TabController _pageController;
PreloadPageController(initialPage: 1);
void _onShare(Map<String, dynamic> content) { void _onShare(Map<String, dynamic> content) {
if (content != null) { if (content != null) {
@ -114,6 +119,7 @@ class _HomeViewState extends State<HomeView> {
void dispose() { void dispose() {
_intentDataStreamSubscription?.cancel(); _intentDataStreamSubscription?.cancel();
_intentFileStreamSubscription?.cancel(); _intentFileStreamSubscription?.cancel();
_pageController.removeListener(_updateCurrentIndex);
super.dispose(); super.dispose();
} }
@ -170,9 +176,6 @@ class _HomeViewState extends State<HomeView> {
fabIcon = Icons.add_outlined; fabIcon = Icons.add_outlined;
break; break;
case 2: case 2:
fabIcon = Icons.group_add_outlined;
break;
case 3:
fabIcon = Icons.domain_outlined; fabIcon = Icons.domain_outlined;
break; break;
} }
@ -182,32 +185,55 @@ class _HomeViewState extends State<HomeView> {
AppBar( AppBar(
centerTitle: false, centerTitle: false,
actions: [ actions: [
IconButton( PopupMenuButton(
icon: Icon(Icons.account_circle_outlined), onSelected: (action) {
onPressed: () => switch (action) {
AdaptivePageLayout.of(context).pushNamed('/settings'), case 'invite':
FluffyShare.share(
L10n.of(context).inviteText(
Matrix.of(context).client.userID,
'https://matrix.to/#/${Matrix.of(context).client.userID}'),
context);
break;
case 'archive':
AdaptivePageLayout.of(context).pushNamed('/archive');
break;
}
},
itemBuilder: (_) => [
PopupMenuItem(
value: 'invite',
child: Text(L10n.of(context).inviteContact),
),
PopupMenuItem(
value: 'archive',
child: Text(L10n.of(context).archive),
),
],
), ),
], ],
title: Text(AppConfig.applicationName)), title: Text(AppConfig.applicationName)),
body: PreloadPageView( body: TabBarView(
controller: _pageController, controller: _pageController,
onPageChanged: (i) => setState(() => currentIndex = i),
children: [ children: [
StatusList(key: Key('StatusList')), StatusList(key: Key('StatusList')),
ChatList( ChatList(
type: ChatListType.messages,
onCustomAppBar: (appBar) => setState(() => this.appBar = appBar),
),
ChatList(
type: ChatListType.groups,
onCustomAppBar: (appBar) => setState(() => this.appBar = appBar), onCustomAppBar: (appBar) => setState(() => this.appBar = appBar),
), ),
Discover(server: _server), Discover(server: _server),
Settings(),
], ],
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: fabIcon == null
? null
: FloatingActionButton(
child: Icon(fabIcon), child: Icon(fabIcon),
onPressed: _onFabTab, onPressed: _onFabTab,
foregroundColor:
currentIndex == 2 ? Theme.of(context).accentColor : null,
backgroundColor: currentIndex == 2
? Theme.of(context).scaffoldBackgroundColor
: null,
), ),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomNavigationBar( bottomNavigationBar: BottomNavigationBar(
@ -219,11 +245,7 @@ class _HomeViewState extends State<HomeView> {
elevation: 20, elevation: 20,
backgroundColor: Theme.of(context).appBarTheme.color, backgroundColor: Theme.of(context).appBarTheme.color,
onTap: (i) { onTap: (i) {
_pageController.animateToPage( _pageController.animateTo(i);
i,
duration: Duration(milliseconds: 200),
curve: Curves.bounceOut,
);
setState(() => currentIndex = i); setState(() => currentIndex = i);
}, },
items: [ items: [
@ -235,14 +257,14 @@ class _HomeViewState extends State<HomeView> {
label: L10n.of(context).messages, label: L10n.of(context).messages,
icon: Icon(CupertinoIcons.chat_bubble_2), icon: Icon(CupertinoIcons.chat_bubble_2),
), ),
BottomNavigationBarItem(
label: L10n.of(context).groups,
icon: Icon(Icons.people_outline),
),
BottomNavigationBarItem( BottomNavigationBarItem(
label: L10n.of(context).discover, label: L10n.of(context).discover,
icon: Icon(CupertinoIcons.search_circle), icon: Icon(CupertinoIcons.search_circle),
), ),
BottomNavigationBarItem(
label: L10n.of(context).settings,
icon: Icon(Icons.settings_outlined),
),
], ],
), ),
); );

View File

@ -8,19 +8,15 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
enum ChatListType { messages, groups, all }
enum SelectMode { normal, select } enum SelectMode { normal, select }
class ChatList extends StatefulWidget { class ChatList extends StatefulWidget {
final String activeChat; final String activeChat;
final ChatListType type;
final void Function(AppBar appBar) onCustomAppBar; final void Function(AppBar appBar) onCustomAppBar;
const ChatList({ const ChatList({
Key key, Key key,
this.activeChat, this.activeChat,
@required this.type,
this.onCustomAppBar, this.onCustomAppBar,
}) : super(key: key); }) : super(key: key);
@override @override
@ -175,11 +171,6 @@ class _ChatListState extends State<ChatList> {
(searchMode && (searchMode &&
!room.displayname.toLowerCase().contains( !room.displayname.toLowerCase().contains(
searchController.text.toLowerCase() ?? ''))); searchController.text.toLowerCase() ?? '')));
if (widget.type == ChatListType.messages) {
rooms.removeWhere((room) => !room.isDirectChat);
} else if (widget.type == ChatListType.groups) {
rooms.removeWhere((room) => room.isDirectChat);
}
if (rooms.isEmpty && (!searchMode)) { if (rooms.isEmpty && (!searchMode)) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -196,6 +187,7 @@ class _ChatListState extends State<ChatList> {
searchMode searchMode
? L10n.of(context).noRoomsFound ? L10n.of(context).noRoomsFound
: L10n.of(context).startYourFirstChat, : L10n.of(context).startYourFirstChat,
textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
color: Colors.grey, color: Colors.grey,
fontSize: 16, fontSize: 16,

View File

@ -19,11 +19,11 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import '../components/content_banner.dart'; import '../../components/content_banner.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import '../components/matrix.dart'; import '../../components/matrix.dart';
import '../app_config.dart'; import '../../app_config.dart';
import '../config/setting_keys.dart'; import '../../config/setting_keys.dart';
class Settings extends StatefulWidget { class Settings extends StatefulWidget {
@override @override
@ -320,38 +320,16 @@ class _SettingsState extends State<Settings> {
return c; return c;
}); });
} }
return Scaffold( return ListView(
body: NestedScrollView( children: <Widget>[
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => ContentBanner(
<Widget>[
SliverAppBar(
leading: BackButton(),
expandedHeight: 300.0,
floating: true,
pinned: true,
backgroundColor: Theme.of(context).appBarTheme.color,
flexibleSpace: FlexibleSpaceBar(
title: Text(
L10n.of(context).settings,
style: TextStyle(
color: Theme.of(context)
.appBarTheme
.textTheme
.headline6
.color),
),
background: ContentBanner(
profile?.avatarUrl, profile?.avatarUrl,
height: 300, height: 200,
opacity: 1,
defaultIcon: Icons.account_circle_outlined, defaultIcon: Icons.account_circle_outlined,
loading: profile == null, loading: profile == null,
onEdit: () => setAvatarAction(context), onEdit: () => setAvatarAction(context),
), ),
),
),
],
body: ListView(
children: <Widget>[
ListTile( ListTile(
title: Text( title: Text(
L10n.of(context).notifications, L10n.of(context).notifications,
@ -533,8 +511,6 @@ class _SettingsState extends State<Settings> {
onTap: () => PlatformInfos.showDialog(context), onTap: () => PlatformInfos.showDialog(context),
), ),
], ],
),
),
); );
} }
} }

View File

@ -2,6 +2,7 @@ import 'package:fluffychat/components/list_items/status_list_tile.dart';
import 'package:fluffychat/components/matrix.dart'; import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/utils/status.dart'; import 'package:fluffychat/utils/status.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
class StatusList extends StatefulWidget { class StatusList extends StatefulWidget {
const StatusList({Key key}) : super(key: key); const StatusList({Key key}) : super(key: key);
@ -22,7 +23,7 @@ class _StatusListState extends State<StatusList> {
elevation: _onlyContacts ? 7 : null, elevation: _onlyContacts ? 7 : null,
color: !_onlyContacts ? null : Theme.of(context).primaryColor, color: !_onlyContacts ? null : Theme.of(context).primaryColor,
child: Text( child: Text(
'Contacts', L10n.of(context).contacts,
style: TextStyle(color: _onlyContacts ? Colors.white : null), style: TextStyle(color: _onlyContacts ? Colors.white : null),
), ),
onPressed: () => setState(() => _onlyContacts = true), onPressed: () => setState(() => _onlyContacts = true),
@ -31,7 +32,7 @@ class _StatusListState extends State<StatusList> {
elevation: !_onlyContacts ? 7 : null, elevation: !_onlyContacts ? 7 : null,
color: _onlyContacts ? null : Theme.of(context).primaryColor, color: _onlyContacts ? null : Theme.of(context).primaryColor,
child: Text( child: Text(
'All', L10n.of(context).all,
style: TextStyle(color: !_onlyContacts ? Colors.white : null), style: TextStyle(color: !_onlyContacts ? Colors.white : null),
), ),
onPressed: () => setState(() => _onlyContacts = false), onPressed: () => setState(() => _onlyContacts = false),
@ -53,6 +54,16 @@ class _StatusListState extends State<StatusList> {
statuses.removeWhere( statuses.removeWhere(
(p) => client.getDirectChatFromUserId(p.senderId) == null); (p) => client.getDirectChatFromUserId(p.senderId) == null);
} }
if (statuses.isEmpty) {
return Container(
padding: EdgeInsets.all(16),
alignment: Alignment.center,
child: Text(
L10n.of(context).noStatusesFound,
textAlign: TextAlign.center,
),
);
}
return ListView.separated( return ListView.separated(
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,

View File

@ -87,8 +87,18 @@ class _NewPrivateChatState extends State<NewPrivateChat> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
leading: BackButton(), leading: BackButton(),
title: Text(L10n.of(context).newPrivateChat), title: Text(L10n.of(context).newChat),
elevation: 0, elevation: 0,
actions: [
FlatButton(
child: Text(
L10n.of(context).createNewGroup,
style: TextStyle(color: Theme.of(context).accentColor),
),
onPressed: () => AdaptivePageLayout.of(context)
.pushNamedAndRemoveUntilIsFirst('/newgroup'),
)
],
), ),
body: Column( body: Column(
children: <Widget>[ children: <Widget>[

View File

@ -19,9 +19,7 @@ class ShareView extends StatelessWidget {
), ),
title: Text(L10n.of(context).share), title: Text(L10n.of(context).share),
), ),
body: ChatList( body: ChatList(),
type: ChatListType.all,
),
); );
} }
} }

View File

@ -872,13 +872,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.0-nullsafety.2" version: "1.5.0-nullsafety.2"
preload_page_view:
dependency: "direct main"
description:
name: preload_page_view
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
process: process:
dependency: transitive dependency: transitive
description: description:

View File

@ -31,7 +31,6 @@ dependencies:
adaptive_page_layout: ^0.1.6 adaptive_page_layout: ^0.1.6
provider: ^4.3.3 provider: ^4.3.3
adaptive_theme: ^1.1.0 adaptive_theme: ^1.1.0
preload_page_view: ^0.1.4
# desktop_notifications: ^0.0.0-dev.4 // Currently blocked by: https://github.com/canonical/desktop_notifications.dart/issues/5 # desktop_notifications: ^0.0.0-dev.4 // Currently blocked by: https://github.com/canonical/desktop_notifications.dart/issues/5
matrix_link_text: ^0.3.2 matrix_link_text: ^0.3.2
path_provider: ^1.6.27 path_provider: ^1.6.27