mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 09:08:40 +00:00
fix #81
This commit is contained in:
parent
42330594bb
commit
d25f4cb36d
8 changed files with 269 additions and 45 deletions
|
|
@ -27,17 +27,30 @@ class _UserContextMenuState extends State<UserContextMenu> {
|
|||
return PieMenu(
|
||||
onPressed: () => (),
|
||||
actions: [
|
||||
PieAction(
|
||||
tooltip: Text(context.lang.contextMenuArchiveUser),
|
||||
onSelect: () async {
|
||||
final update = ContactsCompanion(archived: Value(true));
|
||||
if (context.mounted) {
|
||||
await twonlyDatabase.contactsDao
|
||||
.updateContact(widget.contact.userId, update);
|
||||
}
|
||||
},
|
||||
child: FaIcon(FontAwesomeIcons.boxArchive),
|
||||
),
|
||||
if (!widget.contact.archived)
|
||||
PieAction(
|
||||
tooltip: Text(context.lang.contextMenuArchiveUser),
|
||||
onSelect: () async {
|
||||
final update = ContactsCompanion(archived: Value(true));
|
||||
if (context.mounted) {
|
||||
await twonlyDatabase.contactsDao
|
||||
.updateContact(widget.contact.userId, update);
|
||||
}
|
||||
},
|
||||
child: FaIcon(FontAwesomeIcons.boxArchive),
|
||||
),
|
||||
if (widget.contact.archived)
|
||||
PieAction(
|
||||
tooltip: Text(context.lang.contextMenuUndoArchiveUser),
|
||||
onSelect: () async {
|
||||
final update = ContactsCompanion(archived: Value(false));
|
||||
if (context.mounted) {
|
||||
await twonlyDatabase.contactsDao
|
||||
.updateContact(widget.contact.userId, update);
|
||||
}
|
||||
},
|
||||
child: FaIcon(FontAwesomeIcons.boxOpen),
|
||||
),
|
||||
PieAction(
|
||||
tooltip: Text(context.lang.contextMenuVerifyUser),
|
||||
onSelect: () {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@
|
|||
"@contextMenuVerifyUser": {},
|
||||
"contextMenuArchiveUser": "Archivieren",
|
||||
"@contextMenuArchiveUser": {},
|
||||
"contextMenuUndoArchiveUser": "Archivierung aufheben",
|
||||
"@contextMenuUndoArchiveUser": {},
|
||||
"startNewChatTitle": "Kontakt wählen",
|
||||
"@startNewChatTitle": {},
|
||||
"startNewChatNewContact": "Neuer Kontakt",
|
||||
"@startNewChatNewContact": {},
|
||||
"startNewChatYourContacts": "Deine Kontakte",
|
||||
"@startNewChatYourContacts": {},
|
||||
"contextMenuOpenChat": "Chat",
|
||||
"contextMenuSendImage": "Bild senden",
|
||||
"mediaViewerAuthReason": "Bitte authentifiziere dich, um diesen twonly zu sehen!",
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@
|
|||
"@shareImagedEditorSavedImage": {},
|
||||
"shareImageSearchAllContacts": "Search all contacts",
|
||||
"@shareImageSearchAllContacts": {},
|
||||
"startNewChatTitle": "Select Contact",
|
||||
"@startNewChatTitle": {},
|
||||
"startNewChatNewContact": "New Contact",
|
||||
"@startNewChatNewContact": {},
|
||||
"startNewChatYourContacts": "Your Contacts",
|
||||
"@startNewChatYourContacts": {},
|
||||
"shareImageAllUsers": "All contacts",
|
||||
"@shareImageAllUsers": {},
|
||||
"shareImageAllTwonlyWarning": "twonlies can only be send to verified contacts!",
|
||||
|
|
@ -98,6 +104,8 @@
|
|||
"@contextMenuVerifyUser": {},
|
||||
"contextMenuArchiveUser": "Archive",
|
||||
"@contextMenuArchiveUser": {},
|
||||
"contextMenuUndoArchiveUser": "Undo archiving",
|
||||
"@contextMenuUndoArchiveUser": {},
|
||||
"contextMenuOpenChat": "Open chat",
|
||||
"@contextMenuOpenChat": {},
|
||||
"contextMenuSendImage": "Send image",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:local_auth/local_auth.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:pie_menu/pie_menu.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/src/database/twonly_database.dart';
|
||||
import 'package:twonly/src/proto/api/error.pb.dart';
|
||||
|
|
@ -177,3 +178,27 @@ Future<bool> isAllowedToDownload() async {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PieTheme getPieCanvasTheme(BuildContext context) {
|
||||
return PieTheme(
|
||||
brightness: Theme.of(context).brightness,
|
||||
rightClickShowsMenu: true,
|
||||
radius: 70,
|
||||
buttonTheme: PieButtonTheme(
|
||||
backgroundColor: Theme.of(context).colorScheme.tertiary,
|
||||
iconColor: Theme.of(context).colorScheme.surfaceBright,
|
||||
),
|
||||
buttonThemeHovered: PieButtonTheme(
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
iconColor: Theme.of(context).colorScheme.surfaceBright,
|
||||
),
|
||||
tooltipPadding: EdgeInsets.all(20),
|
||||
overlayColor: const Color.fromARGB(41, 0, 0, 0),
|
||||
|
||||
// spacing: 0,
|
||||
tooltipTextStyle: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import 'package:twonly/src/utils/misc.dart';
|
|||
import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
|
||||
import 'package:twonly/src/views/chats/chat_item_details_view.dart';
|
||||
import 'package:twonly/src/views/chats/media_viewer_view.dart';
|
||||
import 'package:twonly/src/views/chats/start_new_chat.dart';
|
||||
import 'package:twonly/src/views/home_view.dart';
|
||||
import 'package:twonly/src/views/settings/settings_main_view.dart';
|
||||
import 'package:twonly/src/views/chats/search_username_view.dart';
|
||||
|
|
@ -32,18 +33,7 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SettingsMainView(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text("twonly"),
|
||||
),
|
||||
// title:
|
||||
title: Text("twonly"),
|
||||
actions: [
|
||||
StreamBuilder(
|
||||
stream: twonlyDatabase.contactsDao.watchContactsRequested(),
|
||||
|
|
@ -133,6 +123,21 @@ class _ChatListViewState extends State<ChatListView> {
|
|||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30.0),
|
||||
child: FloatingActionButton(
|
||||
foregroundColor: Colors.white,
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return StartNewChat();
|
||||
}),
|
||||
);
|
||||
},
|
||||
child: FaIcon(FontAwesomeIcons.penToSquare),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,12 +184,13 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
|||
floatingActionButton: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30.0),
|
||||
child: FloatingActionButton(
|
||||
foregroundColor: Colors.white,
|
||||
onPressed: () {
|
||||
if (!_isLoading) _addNewUser(context);
|
||||
},
|
||||
child: (_isLoading)
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Icon(Icons.arrow_right_rounded),
|
||||
: FaIcon(FontAwesomeIcons.magnifyingGlassPlus),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
183
lib/src/views/chats/start_new_chat.dart
Normal file
183
lib/src/views/chats/start_new_chat.dart
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:pie_menu/pie_menu.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/components/flame.dart';
|
||||
import 'package:twonly/src/components/headline.dart';
|
||||
import 'package:twonly/src/components/initialsavatar.dart';
|
||||
import 'package:twonly/src/components/user_context_menu.dart';
|
||||
import 'package:twonly/src/database/daos/contacts_dao.dart';
|
||||
import 'package:twonly/src/database/twonly_database.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/chats/chat_item_details_view.dart';
|
||||
import 'package:twonly/src/views/chats/search_username_view.dart';
|
||||
|
||||
class StartNewChat extends StatefulWidget {
|
||||
const StartNewChat({super.key});
|
||||
@override
|
||||
State<StartNewChat> createState() => _StartNewChat();
|
||||
}
|
||||
|
||||
class _StartNewChat extends State<StartNewChat> {
|
||||
List<Contact> contacts = [];
|
||||
List<Contact> allContacts = [];
|
||||
final TextEditingController searchUserName = TextEditingController();
|
||||
late StreamSubscription<List<Contact>> contactSub;
|
||||
int maxTotalMediaCounter = 1000;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
Stream<List<Contact>> stream =
|
||||
twonlyDatabase.contactsDao.watchContactsForShareView();
|
||||
|
||||
contactSub = stream.listen((update) {
|
||||
setState(() {
|
||||
allContacts = update;
|
||||
});
|
||||
filterUsers();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
contactSub.cancel();
|
||||
}
|
||||
|
||||
Future filterUsers() async {
|
||||
if (searchUserName.value.text.isEmpty) {
|
||||
setState(() {
|
||||
contacts = allContacts;
|
||||
});
|
||||
return;
|
||||
}
|
||||
List<Contact> usersFiltered = allContacts
|
||||
.where((user) => getContactDisplayName(user)
|
||||
.toLowerCase()
|
||||
.contains(searchUserName.value.text.toLowerCase()))
|
||||
.toList();
|
||||
setState(() {
|
||||
contacts = usersFiltered;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(context.lang.startNewChatTitle),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: PieCanvas(
|
||||
theme: getPieCanvasTheme(context),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: 40, left: 10, top: 20, right: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: TextField(
|
||||
onChanged: (_) {
|
||||
filterUsers();
|
||||
},
|
||||
decoration: getInputDecoration(
|
||||
context,
|
||||
context.lang.shareImageSearchAllContacts,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: UserList(
|
||||
contacts,
|
||||
maxTotalMediaCounter,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserList extends StatelessWidget {
|
||||
const UserList(
|
||||
this.users,
|
||||
this.maxTotalMediaCounter, {
|
||||
super.key,
|
||||
});
|
||||
final List<Contact> users;
|
||||
final int maxTotalMediaCounter;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Step 1: Sort the users alphabetically
|
||||
users
|
||||
.sort((a, b) => b.lastMessageExchange.compareTo(a.lastMessageExchange));
|
||||
|
||||
return ListView.builder(
|
||||
restorationId: 'new_message_users_list',
|
||||
itemCount: users.length + 2,
|
||||
itemBuilder: (BuildContext context, int i) {
|
||||
if (i == 0) {
|
||||
return ListTile(
|
||||
title: Text(context.lang.startNewChatNewContact),
|
||||
leading: CircleAvatar(
|
||||
child: FaIcon(
|
||||
FontAwesomeIcons.userPlus,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SearchUsernameView(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
if (i == 1) {
|
||||
return HeadLineComponent(context.lang.startNewChatYourContacts);
|
||||
}
|
||||
Contact user = users[i - 2];
|
||||
int flameCounter = getFlameCounterFromContact(user);
|
||||
return UserContextMenu(
|
||||
contact: user,
|
||||
child: ListTile(
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start, // Center horizontally
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center, // Center vertically
|
||||
children: [
|
||||
Text(getContactDisplayName(user)),
|
||||
if (flameCounter >= 1)
|
||||
FlameCounterWidget(
|
||||
user,
|
||||
flameCounter,
|
||||
maxTotalMediaCounter,
|
||||
prefix: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
leading: ContactAvatar(contact: user),
|
||||
onTap: () {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ChatItemDetailsView(user);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:pie_menu/pie_menu.dart';
|
||||
import 'package:twonly/src/services/notification_service.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
|
||||
import 'camera_to_share/camera_preview_view.dart';
|
||||
import 'chats/chat_list_view.dart';
|
||||
|
|
@ -65,27 +66,7 @@ class HomeViewState extends State<HomeView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PieCanvas(
|
||||
theme: PieTheme(
|
||||
brightness: Theme.of(context).brightness,
|
||||
rightClickShowsMenu: true,
|
||||
radius: 70,
|
||||
buttonTheme: PieButtonTheme(
|
||||
backgroundColor: Theme.of(context).colorScheme.tertiary,
|
||||
iconColor: Theme.of(context).colorScheme.surfaceBright,
|
||||
),
|
||||
buttonThemeHovered: PieButtonTheme(
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
iconColor: Theme.of(context).colorScheme.surfaceBright,
|
||||
),
|
||||
tooltipPadding: EdgeInsets.all(20),
|
||||
overlayColor: const Color.fromARGB(41, 0, 0, 0),
|
||||
|
||||
// spacing: 0,
|
||||
tooltipTextStyle: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
theme: getPieCanvasTheme(context),
|
||||
child: Scaffold(
|
||||
body: PageView(
|
||||
controller: homeViewPageController,
|
||||
|
|
|
|||
Loading…
Reference in a new issue