mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-27 14:59:29 +01:00
change: Minor design changes
This commit is contained in:
parent
72604c61f0
commit
2d3c4409a1
@ -11,7 +11,7 @@ class DefaultAppBarSearchField extends StatefulWidget {
|
||||
final bool readOnly;
|
||||
final Widget prefixIcon;
|
||||
|
||||
const DefaultAppBarSearchField({
|
||||
DefaultAppBarSearchField({
|
||||
Key key,
|
||||
this.searchController,
|
||||
this.onChanged,
|
||||
@ -25,14 +25,16 @@ class DefaultAppBarSearchField extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DefaultAppBarSearchFieldState createState() =>
|
||||
_DefaultAppBarSearchFieldState();
|
||||
DefaultAppBarSearchFieldState createState() =>
|
||||
DefaultAppBarSearchFieldState();
|
||||
}
|
||||
|
||||
class _DefaultAppBarSearchFieldState extends State<DefaultAppBarSearchField> {
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
class DefaultAppBarSearchFieldState extends State<DefaultAppBarSearchField> {
|
||||
TextEditingController _searchController;
|
||||
bool _lastTextWasEmpty = false;
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
|
||||
void requestFocus() => _focusNode.requestFocus();
|
||||
|
||||
void _updateSearchController() {
|
||||
final thisTextIsEmpty = _searchController.text?.isEmpty ?? false;
|
||||
|
@ -1035,6 +1035,11 @@
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"addNewContact": "Add new contact",
|
||||
"@addNewContact": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"newVerificationRequest": "New verification request!",
|
||||
"@newVerificationRequest": {
|
||||
"type": "text",
|
||||
|
@ -4,7 +4,6 @@ import 'dart:io';
|
||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:adaptive_page_layout/adaptive_page_layout.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/share_view.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -179,20 +178,30 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
}
|
||||
}
|
||||
|
||||
final StreamController<int> _onAppBarButtonTap =
|
||||
StreamController<int>.broadcast();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_onShareContentChanged ??=
|
||||
Matrix.of(context).onShareContentChanged.stream.listen(_onShare);
|
||||
IconData fabIcon;
|
||||
String title;
|
||||
switch (currentIndex) {
|
||||
case 0:
|
||||
fabIcon = Icons.edit_outlined;
|
||||
title = L10n.of(context).contacts;
|
||||
break;
|
||||
case 1:
|
||||
fabIcon = Icons.add_outlined;
|
||||
title = AppConfig.applicationName;
|
||||
break;
|
||||
case 2:
|
||||
fabIcon = Icons.domain_outlined;
|
||||
title = L10n.of(context).discover;
|
||||
break;
|
||||
case 3:
|
||||
title = L10n.of(context).settings;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -201,43 +210,27 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
AppBar(
|
||||
centerTitle: false,
|
||||
actions: [
|
||||
PopupMenuButton(
|
||||
onSelected: (action) {
|
||||
switch (action) {
|
||||
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),
|
||||
),
|
||||
],
|
||||
IconButton(
|
||||
icon: Icon(currentIndex == 3
|
||||
? Icons.exit_to_app_outlined
|
||||
: Icons.search_outlined),
|
||||
onPressed: () => _pageController.indexIsChanging
|
||||
? null
|
||||
: _onAppBarButtonTap.add(currentIndex),
|
||||
),
|
||||
],
|
||||
title: Text(AppConfig.applicationName)),
|
||||
title: Text(title)),
|
||||
body: TabBarView(
|
||||
controller: _pageController,
|
||||
children: [
|
||||
ContactList(),
|
||||
ContactList(onAppBarButtonTap: _onAppBarButtonTap.stream),
|
||||
ChatList(
|
||||
onCustomAppBar: (appBar) => setState(() => this.appBar = appBar),
|
||||
onAppBarButtonTap: _onAppBarButtonTap.stream,
|
||||
),
|
||||
Discover(server: _server),
|
||||
Settings(),
|
||||
Discover(
|
||||
server: _server, onAppBarButtonTap: _onAppBarButtonTap.stream),
|
||||
Settings(onAppBarButtonTap: _onAppBarButtonTap.stream),
|
||||
],
|
||||
),
|
||||
floatingActionButton: fabIcon == null
|
||||
@ -258,7 +251,6 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
showSelectedLabels: true,
|
||||
showUnselectedLabels: false,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
elevation: 20,
|
||||
backgroundColor: Theme.of(context).appBarTheme.color,
|
||||
onTap: (i) {
|
||||
_pageController.animateTo(i);
|
||||
@ -275,7 +267,7 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: L10n.of(context).discover,
|
||||
icon: Icon(CupertinoIcons.search_circle),
|
||||
icon: Icon(CupertinoIcons.compass),
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
label: L10n.of(context).settings,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:fluffychat/components/connection_status_header.dart';
|
||||
@ -13,11 +15,13 @@ enum SelectMode { normal, select }
|
||||
class ChatList extends StatefulWidget {
|
||||
final String activeChat;
|
||||
final void Function(AppBar appBar) onCustomAppBar;
|
||||
final Stream onAppBarButtonTap;
|
||||
|
||||
const ChatList({
|
||||
Key key,
|
||||
this.activeChat,
|
||||
this.onCustomAppBar,
|
||||
this.onAppBarButtonTap,
|
||||
}) : super(key: key);
|
||||
@override
|
||||
_ChatListState createState() => _ChatListState();
|
||||
@ -28,6 +32,32 @@ class _ChatListState extends State<ChatList> {
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
final _selectedRoomIds = <String>{};
|
||||
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
StreamSubscription _onAppBarButtonTapSub;
|
||||
final GlobalKey<DefaultAppBarSearchFieldState> _searchField = GlobalKey();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_onAppBarButtonTapSub =
|
||||
widget.onAppBarButtonTap.where((i) => i == 1).listen((_) async {
|
||||
await _scrollController.animateTo(
|
||||
_scrollController.position.minScrollExtent,
|
||||
duration: Duration(milliseconds: 200),
|
||||
curve: Curves.ease,
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => _searchField.currentState.requestFocus(),
|
||||
);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_onAppBarButtonTapSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _toggleSelection(String roomId) {
|
||||
setState(() => _selectedRoomIds.contains(roomId)
|
||||
? _selectedRoomIds.remove(roomId)
|
||||
@ -198,11 +228,13 @@ class _ChatListState extends State<ChatList> {
|
||||
}
|
||||
final totalCount = rooms.length;
|
||||
return ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: totalCount + 1,
|
||||
itemBuilder: (BuildContext context, int i) => i == 0
|
||||
? Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: DefaultAppBarSearchField(
|
||||
key: _searchField,
|
||||
hintText: L10n.of(context).search,
|
||||
prefixIcon: Icon(Icons.search_outlined),
|
||||
searchController: searchController,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||
import 'package:fluffychat/components/avatar.dart';
|
||||
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
||||
@ -8,65 +10,98 @@ import '../../utils/client_presence_extension.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class ContactList extends StatefulWidget {
|
||||
final Stream onAppBarButtonTap;
|
||||
|
||||
const ContactList({Key key, this.onAppBarButtonTap}) : super(key: key);
|
||||
@override
|
||||
_ContactListState createState() => _ContactListState();
|
||||
}
|
||||
|
||||
class _ContactListState extends State<ContactList> {
|
||||
String _searchQuery = '';
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
StreamSubscription _onAppBarButtonTapSub;
|
||||
final GlobalKey<DefaultAppBarSearchFieldState> _searchField = GlobalKey();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_onAppBarButtonTapSub =
|
||||
widget.onAppBarButtonTap.where((i) => i == 0).listen((_) async {
|
||||
await _scrollController.animateTo(
|
||||
_scrollController.position.minScrollExtent,
|
||||
duration: Duration(milliseconds: 200),
|
||||
curve: Curves.ease,
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => _searchField.currentState.requestFocus(),
|
||||
);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_onAppBarButtonTapSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: DefaultAppBarSearchField(
|
||||
hintText: L10n.of(context).search,
|
||||
prefixIcon: Icon(Icons.search_outlined),
|
||||
onChanged: (t) => setState(() => _searchQuery = t),
|
||||
padding: EdgeInsets.zero,
|
||||
return ListView(
|
||||
controller: _scrollController,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: DefaultAppBarSearchField(
|
||||
key: _searchField,
|
||||
hintText: L10n.of(context).search,
|
||||
prefixIcon: Icon(Icons.search_outlined),
|
||||
onChanged: (t) => setState(() => _searchQuery = t),
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
child: Icon(Icons.add_outlined),
|
||||
radius: Avatar.defaultSize / 2,
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
child: Icon(Icons.add_outlined),
|
||||
radius: Avatar.defaultSize / 2,
|
||||
),
|
||||
title: Text(L10n.of(context).addNewContact),
|
||||
onTap: () =>
|
||||
AdaptivePageLayout.of(context).pushNamed('/newprivatechat'),
|
||||
),
|
||||
title: Text('Add new contact'),
|
||||
onTap: () =>
|
||||
AdaptivePageLayout.of(context).pushNamed('/newprivatechat'),
|
||||
),
|
||||
Divider(height: 1),
|
||||
StreamBuilder<Object>(
|
||||
stream: Matrix.of(context).client.onSync.stream,
|
||||
builder: (context, snapshot) {
|
||||
final contactList = Matrix.of(context)
|
||||
.client
|
||||
.contactList
|
||||
.where((p) => p.senderId
|
||||
.toLowerCase()
|
||||
.contains(_searchQuery.toLowerCase()))
|
||||
.toList();
|
||||
if (contactList.isEmpty) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'No contacts found...',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Divider(height: 1),
|
||||
StreamBuilder<Object>(
|
||||
stream: Matrix.of(context).client.onSync.stream,
|
||||
builder: (context, snapshot) {
|
||||
final contactList = Matrix.of(context)
|
||||
.client
|
||||
.contactList
|
||||
.where((p) => p.senderId
|
||||
.toLowerCase()
|
||||
.contains(_searchQuery.toLowerCase()))
|
||||
.toList();
|
||||
if (contactList.isEmpty) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'No contacts found...',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(bottom: 24),
|
||||
itemCount: contactList.length,
|
||||
itemBuilder: (context, i) =>
|
||||
ContactListTile(contact: contactList[i]),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.only(bottom: 24),
|
||||
itemCount: contactList.length,
|
||||
itemBuilder: (context, i) =>
|
||||
ContactListTile(contact: contactList[i]),
|
||||
);
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,13 @@ class Discover extends StatefulWidget {
|
||||
final String alias;
|
||||
|
||||
final String server;
|
||||
final Stream onAppBarButtonTap;
|
||||
|
||||
const Discover({
|
||||
Key key,
|
||||
this.alias,
|
||||
this.server,
|
||||
this.onAppBarButtonTap,
|
||||
}) : super(key: key);
|
||||
@override
|
||||
_DiscoverState createState() => _DiscoverState();
|
||||
@ -29,6 +31,16 @@ class _DiscoverState extends State<Discover> {
|
||||
Timer _coolDown;
|
||||
String _genericSearchTerm;
|
||||
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
StreamSubscription _onAppBarButtonTapSub;
|
||||
final GlobalKey<DefaultAppBarSearchFieldState> _searchField = GlobalKey();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_onAppBarButtonTapSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _search(BuildContext context, String query) async {
|
||||
_coolDown?.cancel();
|
||||
_coolDown = Timer(
|
||||
@ -86,6 +98,17 @@ class _DiscoverState extends State<Discover> {
|
||||
@override
|
||||
void initState() {
|
||||
_genericSearchTerm = widget.alias;
|
||||
_onAppBarButtonTapSub =
|
||||
widget.onAppBarButtonTap.where((i) => i == 2).listen((_) async {
|
||||
await _scrollController.animateTo(
|
||||
_scrollController.position.minScrollExtent,
|
||||
duration: Duration(milliseconds: 200),
|
||||
curve: Curves.ease,
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => _searchField.currentState.requestFocus(),
|
||||
);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@ -121,10 +144,12 @@ class _DiscoverState extends State<Discover> {
|
||||
return res;
|
||||
});
|
||||
return ListView(
|
||||
controller: _scrollController,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(12),
|
||||
child: DefaultAppBarSearchField(
|
||||
key: _searchField,
|
||||
hintText: L10n.of(context).search,
|
||||
prefixIcon: Icon(Icons.search_outlined),
|
||||
onChanged: (t) => _search(context, t),
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||
import 'package:fluffychat/components/dialogs/bootstrap_dialog.dart';
|
||||
@ -26,6 +28,9 @@ import '../../app_config.dart';
|
||||
import '../../config/setting_keys.dart';
|
||||
|
||||
class Settings extends StatefulWidget {
|
||||
final Stream onAppBarButtonTap;
|
||||
|
||||
const Settings({Key key, this.onAppBarButtonTap}) : super(key: key);
|
||||
@override
|
||||
_SettingsState createState() => _SettingsState();
|
||||
}
|
||||
@ -37,6 +42,21 @@ class _SettingsState extends State<Settings> {
|
||||
bool crossSigningCached;
|
||||
Future<bool> megolmBackupCachedFuture;
|
||||
bool megolmBackupCached;
|
||||
StreamSubscription _onAppBarButtonTapSub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_onAppBarButtonTapSub = widget.onAppBarButtonTap
|
||||
.where((i) => i == 3)
|
||||
.listen((_) => logoutAction(context));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_onAppBarButtonTapSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void logoutAction(BuildContext context) async {
|
||||
if (await showOkCancelAlertDialog(
|
||||
|
Loading…
Reference in New Issue
Block a user