mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-02-25 19:00:45 +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 bool readOnly;
|
||||||
final Widget prefixIcon;
|
final Widget prefixIcon;
|
||||||
|
|
||||||
const DefaultAppBarSearchField({
|
DefaultAppBarSearchField({
|
||||||
Key key,
|
Key key,
|
||||||
this.searchController,
|
this.searchController,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
@ -25,14 +25,16 @@ class DefaultAppBarSearchField extends StatefulWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DefaultAppBarSearchFieldState createState() =>
|
DefaultAppBarSearchFieldState createState() =>
|
||||||
_DefaultAppBarSearchFieldState();
|
DefaultAppBarSearchFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DefaultAppBarSearchFieldState extends State<DefaultAppBarSearchField> {
|
class DefaultAppBarSearchFieldState extends State<DefaultAppBarSearchField> {
|
||||||
final FocusNode _focusNode = FocusNode();
|
|
||||||
TextEditingController _searchController;
|
TextEditingController _searchController;
|
||||||
bool _lastTextWasEmpty = false;
|
bool _lastTextWasEmpty = false;
|
||||||
|
final FocusNode _focusNode = FocusNode();
|
||||||
|
|
||||||
|
void requestFocus() => _focusNode.requestFocus();
|
||||||
|
|
||||||
void _updateSearchController() {
|
void _updateSearchController() {
|
||||||
final thisTextIsEmpty = _searchController.text?.isEmpty ?? false;
|
final thisTextIsEmpty = _searchController.text?.isEmpty ?? false;
|
||||||
|
@ -1035,6 +1035,11 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"addNewContact": "Add new contact",
|
||||||
|
"@addNewContact": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"newVerificationRequest": "New verification request!",
|
"newVerificationRequest": "New verification request!",
|
||||||
"@newVerificationRequest": {
|
"@newVerificationRequest": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -4,7 +4,6 @@ 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';
|
||||||
@ -179,20 +178,30 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final StreamController<int> _onAppBarButtonTap =
|
||||||
|
StreamController<int>.broadcast();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_onShareContentChanged ??=
|
_onShareContentChanged ??=
|
||||||
Matrix.of(context).onShareContentChanged.stream.listen(_onShare);
|
Matrix.of(context).onShareContentChanged.stream.listen(_onShare);
|
||||||
IconData fabIcon;
|
IconData fabIcon;
|
||||||
|
String title;
|
||||||
switch (currentIndex) {
|
switch (currentIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
fabIcon = Icons.edit_outlined;
|
fabIcon = Icons.edit_outlined;
|
||||||
|
title = L10n.of(context).contacts;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fabIcon = Icons.add_outlined;
|
fabIcon = Icons.add_outlined;
|
||||||
|
title = AppConfig.applicationName;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
fabIcon = Icons.domain_outlined;
|
fabIcon = Icons.domain_outlined;
|
||||||
|
title = L10n.of(context).discover;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
title = L10n.of(context).settings;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,43 +210,27 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
|||||||
AppBar(
|
AppBar(
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
actions: [
|
actions: [
|
||||||
PopupMenuButton(
|
IconButton(
|
||||||
onSelected: (action) {
|
icon: Icon(currentIndex == 3
|
||||||
switch (action) {
|
? Icons.exit_to_app_outlined
|
||||||
case 'invite':
|
: Icons.search_outlined),
|
||||||
FluffyShare.share(
|
onPressed: () => _pageController.indexIsChanging
|
||||||
L10n.of(context).inviteText(
|
? null
|
||||||
Matrix.of(context).client.userID,
|
: _onAppBarButtonTap.add(currentIndex),
|
||||||
'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(title)),
|
||||||
],
|
|
||||||
title: Text(AppConfig.applicationName)),
|
|
||||||
body: TabBarView(
|
body: TabBarView(
|
||||||
controller: _pageController,
|
controller: _pageController,
|
||||||
children: [
|
children: [
|
||||||
ContactList(),
|
ContactList(onAppBarButtonTap: _onAppBarButtonTap.stream),
|
||||||
ChatList(
|
ChatList(
|
||||||
onCustomAppBar: (appBar) => setState(() => this.appBar = appBar),
|
onCustomAppBar: (appBar) => setState(() => this.appBar = appBar),
|
||||||
|
onAppBarButtonTap: _onAppBarButtonTap.stream,
|
||||||
),
|
),
|
||||||
Discover(server: _server),
|
Discover(
|
||||||
Settings(),
|
server: _server, onAppBarButtonTap: _onAppBarButtonTap.stream),
|
||||||
|
Settings(onAppBarButtonTap: _onAppBarButtonTap.stream),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
floatingActionButton: fabIcon == null
|
floatingActionButton: fabIcon == null
|
||||||
@ -258,7 +251,6 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
|||||||
showSelectedLabels: true,
|
showSelectedLabels: true,
|
||||||
showUnselectedLabels: false,
|
showUnselectedLabels: false,
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
elevation: 20,
|
|
||||||
backgroundColor: Theme.of(context).appBarTheme.color,
|
backgroundColor: Theme.of(context).appBarTheme.color,
|
||||||
onTap: (i) {
|
onTap: (i) {
|
||||||
_pageController.animateTo(i);
|
_pageController.animateTo(i);
|
||||||
@ -275,7 +267,7 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
|||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
label: L10n.of(context).discover,
|
label: L10n.of(context).discover,
|
||||||
icon: Icon(CupertinoIcons.search_circle),
|
icon: Icon(CupertinoIcons.compass),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
label: L10n.of(context).settings,
|
label: L10n.of(context).settings,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/connection_status_header.dart';
|
import 'package:fluffychat/components/connection_status_header.dart';
|
||||||
@ -13,11 +15,13 @@ enum SelectMode { normal, select }
|
|||||||
class ChatList extends StatefulWidget {
|
class ChatList extends StatefulWidget {
|
||||||
final String activeChat;
|
final String activeChat;
|
||||||
final void Function(AppBar appBar) onCustomAppBar;
|
final void Function(AppBar appBar) onCustomAppBar;
|
||||||
|
final Stream onAppBarButtonTap;
|
||||||
|
|
||||||
const ChatList({
|
const ChatList({
|
||||||
Key key,
|
Key key,
|
||||||
this.activeChat,
|
this.activeChat,
|
||||||
this.onCustomAppBar,
|
this.onCustomAppBar,
|
||||||
|
this.onAppBarButtonTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
_ChatListState createState() => _ChatListState();
|
_ChatListState createState() => _ChatListState();
|
||||||
@ -28,6 +32,32 @@ class _ChatListState extends State<ChatList> {
|
|||||||
final TextEditingController searchController = TextEditingController();
|
final TextEditingController searchController = TextEditingController();
|
||||||
final _selectedRoomIds = <String>{};
|
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) {
|
void _toggleSelection(String roomId) {
|
||||||
setState(() => _selectedRoomIds.contains(roomId)
|
setState(() => _selectedRoomIds.contains(roomId)
|
||||||
? _selectedRoomIds.remove(roomId)
|
? _selectedRoomIds.remove(roomId)
|
||||||
@ -198,11 +228,13 @@ class _ChatListState extends State<ChatList> {
|
|||||||
}
|
}
|
||||||
final totalCount = rooms.length;
|
final totalCount = rooms.length;
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
controller: _scrollController,
|
||||||
itemCount: totalCount + 1,
|
itemCount: totalCount + 1,
|
||||||
itemBuilder: (BuildContext context, int i) => i == 0
|
itemBuilder: (BuildContext context, int i) => i == 0
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: EdgeInsets.all(12),
|
padding: EdgeInsets.all(12),
|
||||||
child: DefaultAppBarSearchField(
|
child: DefaultAppBarSearchField(
|
||||||
|
key: _searchField,
|
||||||
hintText: L10n.of(context).search,
|
hintText: L10n.of(context).search,
|
||||||
prefixIcon: Icon(Icons.search_outlined),
|
prefixIcon: Icon(Icons.search_outlined),
|
||||||
searchController: searchController,
|
searchController: searchController,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
||||||
@ -8,18 +10,50 @@ import '../../utils/client_presence_extension.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
class ContactList extends StatefulWidget {
|
class ContactList extends StatefulWidget {
|
||||||
|
final Stream onAppBarButtonTap;
|
||||||
|
|
||||||
|
const ContactList({Key key, this.onAppBarButtonTap}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
_ContactListState createState() => _ContactListState();
|
_ContactListState createState() => _ContactListState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ContactListState extends State<ContactList> {
|
class _ContactListState extends State<ContactList> {
|
||||||
String _searchQuery = '';
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(children: [
|
return ListView(
|
||||||
|
controller: _scrollController,
|
||||||
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(12),
|
padding: EdgeInsets.all(12),
|
||||||
child: DefaultAppBarSearchField(
|
child: DefaultAppBarSearchField(
|
||||||
|
key: _searchField,
|
||||||
hintText: L10n.of(context).search,
|
hintText: L10n.of(context).search,
|
||||||
prefixIcon: Icon(Icons.search_outlined),
|
prefixIcon: Icon(Icons.search_outlined),
|
||||||
onChanged: (t) => setState(() => _searchQuery = t),
|
onChanged: (t) => setState(() => _searchQuery = t),
|
||||||
@ -33,7 +67,7 @@ class _ContactListState extends State<ContactList> {
|
|||||||
child: Icon(Icons.add_outlined),
|
child: Icon(Icons.add_outlined),
|
||||||
radius: Avatar.defaultSize / 2,
|
radius: Avatar.defaultSize / 2,
|
||||||
),
|
),
|
||||||
title: Text('Add new contact'),
|
title: Text(L10n.of(context).addNewContact),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
AdaptivePageLayout.of(context).pushNamed('/newprivatechat'),
|
AdaptivePageLayout.of(context).pushNamed('/newprivatechat'),
|
||||||
),
|
),
|
||||||
@ -67,6 +101,7 @@ class _ContactListState extends State<ContactList> {
|
|||||||
ContactListTile(contact: contactList[i]),
|
ContactListTile(contact: contactList[i]),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,13 @@ class Discover extends StatefulWidget {
|
|||||||
final String alias;
|
final String alias;
|
||||||
|
|
||||||
final String server;
|
final String server;
|
||||||
|
final Stream onAppBarButtonTap;
|
||||||
|
|
||||||
const Discover({
|
const Discover({
|
||||||
Key key,
|
Key key,
|
||||||
this.alias,
|
this.alias,
|
||||||
this.server,
|
this.server,
|
||||||
|
this.onAppBarButtonTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
_DiscoverState createState() => _DiscoverState();
|
_DiscoverState createState() => _DiscoverState();
|
||||||
@ -29,6 +31,16 @@ class _DiscoverState extends State<Discover> {
|
|||||||
Timer _coolDown;
|
Timer _coolDown;
|
||||||
String _genericSearchTerm;
|
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 {
|
void _search(BuildContext context, String query) async {
|
||||||
_coolDown?.cancel();
|
_coolDown?.cancel();
|
||||||
_coolDown = Timer(
|
_coolDown = Timer(
|
||||||
@ -86,6 +98,17 @@ class _DiscoverState extends State<Discover> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_genericSearchTerm = widget.alias;
|
_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();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,10 +144,12 @@ class _DiscoverState extends State<Discover> {
|
|||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
return ListView(
|
return ListView(
|
||||||
|
controller: _scrollController,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(12),
|
padding: EdgeInsets.all(12),
|
||||||
child: DefaultAppBarSearchField(
|
child: DefaultAppBarSearchField(
|
||||||
|
key: _searchField,
|
||||||
hintText: L10n.of(context).search,
|
hintText: L10n.of(context).search,
|
||||||
prefixIcon: Icon(Icons.search_outlined),
|
prefixIcon: Icon(Icons.search_outlined),
|
||||||
onChanged: (t) => _search(context, t),
|
onChanged: (t) => _search(context, t),
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
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:fluffychat/components/dialogs/bootstrap_dialog.dart';
|
import 'package:fluffychat/components/dialogs/bootstrap_dialog.dart';
|
||||||
@ -26,6 +28,9 @@ import '../../app_config.dart';
|
|||||||
import '../../config/setting_keys.dart';
|
import '../../config/setting_keys.dart';
|
||||||
|
|
||||||
class Settings extends StatefulWidget {
|
class Settings extends StatefulWidget {
|
||||||
|
final Stream onAppBarButtonTap;
|
||||||
|
|
||||||
|
const Settings({Key key, this.onAppBarButtonTap}) : super(key: key);
|
||||||
@override
|
@override
|
||||||
_SettingsState createState() => _SettingsState();
|
_SettingsState createState() => _SettingsState();
|
||||||
}
|
}
|
||||||
@ -37,6 +42,21 @@ class _SettingsState extends State<Settings> {
|
|||||||
bool crossSigningCached;
|
bool crossSigningCached;
|
||||||
Future<bool> megolmBackupCachedFuture;
|
Future<bool> megolmBackupCachedFuture;
|
||||||
bool megolmBackupCached;
|
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 {
|
void logoutAction(BuildContext context) async {
|
||||||
if (await showOkCancelAlertDialog(
|
if (await showOkCancelAlertDialog(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user