Skip to content

Commit

Permalink
Merge pull request #32 from Tawkie/feature-hide-bots
Browse files Browse the repository at this point in the history
Feature hide bots
  • Loading branch information
VincePaulin authored Jul 23, 2024
2 parents 5f8ed61 + f9f2f4c commit 86fa322
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 29 deletions.
7 changes: 6 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2683,5 +2683,10 @@
"privacyTextPrivacy": "privacy policy",
"privacyTextAnd": " and ",
"privacyTextTerms": "terms of service",
"createGroupLimitationWarning": "Only Tawkie / Matrix users can be added to a group chat."
"createGroupLimitationWarning": "Only Tawkie / Matrix users can be added to a group chat.",
"seeBotsRoom":"See bots",
"leaveTheConvDesc": "Do you really want to leave this conversation?",
"leaveTheConvSuccess": "You have left the conversation.",
"chatBotRoomsTitle": "Bots conversations",
"chatBotRoomsNotFound": "No conversation with bots."
}
7 changes: 6 additions & 1 deletion assets/l10n/intl_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2499,5 +2499,10 @@
"privacyTextPrivacy": "politiques de confidentialité",
"privacyTextAnd": " et ",
"privacyTextTerms": "conditions générales d’utilisation et de services",
"createGroupLimitationWarning": "Seul.es les utilisateur.ices Tawkie peuvent être rajouté.es aux groupes."
"createGroupLimitationWarning": "Seul.es les utilisateur.ices Tawkie peuvent être rajouté.es aux groupes.",
"seeBotsRoom":"Voir les bots",
"leaveTheConvDesc": "Voulez-vous vraiment quitter cette conversation ?",
"leaveTheConvSuccess": "Vous avez quitté la conversation.",
"chatBotRoomsTitle": "Conversations des bots",
"chatBotRoomsNotFound": "Aucune conversation avec les bots."
}
32 changes: 31 additions & 1 deletion lib/pages/add_bridge/add_bridge.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:tawkie/widgets/matrix.dart';
import 'package:tawkie/widgets/notifier_state.dart';
import 'package:webview_cookie_manager/webview_cookie_manager.dart';

import 'bot_chat_list.dart';
import 'connection_bridge_dialog.dart';
import 'delete_conversation_dialog.dart';
import 'error_message_dialog.dart';
Expand Down Expand Up @@ -90,7 +91,36 @@ class BotController extends State<AddBridge> {
continueProcess = false;
}

/// Get or create a direct chat with the bot
List<String> getBotIds() {
return SocialNetworkManager.socialNetworks
.map((sn) => sn.chatBot + hostname)
.toList();
}

List<String> get botIds => getBotIds();

void showPopupMenu(BuildContext context) async {
await showMenu(
context: context,
position: const RelativeRect.fromLTRB(100, 80, 0, 100),
items: [
PopupMenuItem(
value: 'see_bots',
child: Text(L10n.of(context)!.seeBotsRoom),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BotChatListPage(botUserIds: botIds),
),
);
},
),
],
elevation: 8.0,
);
}

Future<String?> _getOrCreateDirectChat(String botUserId) async {
try {
await waitForMatrixSync(); // Make sure all conversations are loaded
Expand Down
50 changes: 32 additions & 18 deletions lib/pages/add_bridge/add_bridge_body.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import 'package:tawkie/pages/add_bridge/add_bridge.dart';
import 'package:tawkie/pages/add_bridge/social_network_item.dart';
import 'package:tawkie/utils/platform_infos.dart';
import 'package:tawkie/utils/platform_size.dart';

import 'add_bridge_header.dart';
import 'model/social_network.dart';

// Page offering brigde bot connections to social network chats
class AddBridgeBody extends StatelessWidget {
final BotController controller;

const AddBridgeBody({
super.key,
required this.controller,
Expand All @@ -19,23 +21,32 @@ class AddBridgeBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
controller.showPopupMenu(context);
},
),
],
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
buildHeaderBridgeText(context),
buildHeaderBridgeSubText(context),
PlatformInfos.isWeb ||
PlatformInfos.isDesktop ||
PlatformInfos.isWindows ||
PlatformInfos.isMacOS
PlatformInfos.isDesktop ||
PlatformInfos.isWindows ||
PlatformInfos.isMacOS
? ElevatedButton(
onPressed: () {
// controller.handleRefresh();
},
child: Text(L10n.of(context)!.refreshList),
)
onPressed: () {
// controller.handleRefresh();
},
child: Text(L10n.of(context)!.refreshList),
)
: Container(),
const SizedBox(
height: 10,
Expand All @@ -56,16 +67,19 @@ class AddBridgeBody extends StatelessWidget {
controller.socialNetworks[index].name,
),
// Different build of subtle depending on the social network, for now only Instagram
subtitle: buildSubtitle(context, controller.socialNetworks[index]),
trailing: controller.socialNetworks[index].error == false
? const Icon(
CupertinoIcons.right_chevron,
)
: const Icon(
CupertinoIcons.refresh_bold,
),
subtitle: buildSubtitle(
context, controller.socialNetworks[index]),
trailing:
controller.socialNetworks[index].error == false
? const Icon(
CupertinoIcons.right_chevron,
)
: const Icon(
CupertinoIcons.refresh_bold,
),
// Different ways of connecting and disconnecting depending on the social network
onTap: () => controller.handleSocialNetworkAction(controller.socialNetworks[index]),
onTap: () => controller.handleSocialNetworkAction(
controller.socialNetworks[index]),
);
},
),
Expand Down
148 changes: 148 additions & 0 deletions lib/pages/add_bridge/bot_chat_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';
import 'package:tawkie/pages/chat/chat.dart';
import 'package:tawkie/pages/chat_list/chat_list_item.dart';
import 'package:tawkie/widgets/matrix.dart';

class BotChatListPage extends StatefulWidget {
final List<String> botUserIds;

const BotChatListPage({super.key, required this.botUserIds});

@override
State<BotChatListPage> createState() => _BotChatListPageState();
}

class _BotChatListPageState extends State<BotChatListPage> {
Future<List<Room>>? _roomsFuture;

@override
void initState() {
super.initState();
_loadRooms();
}

void _loadRooms() {
setState(() {
_roomsFuture = Future.delayed(
Duration.zero,
() => Matrix.of(context)
.client
.rooms
.where((room) => widget.botUserIds.contains(room.directChatMatrixID))
.toList(),
);
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(L10n.of(context)!.chatBotRoomsTitle),
),
body: FutureBuilder<List<Room>>(
future: _roomsFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(
child: Text('${L10n.of(context)!.err_} ${snapshot.error}')
);
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text(L10n.of(context)!.chatBotRoomsNotFound));
} else {
final rooms = snapshot.data!;
return ListView.builder(
itemCount: rooms.length,
itemBuilder: (context, i) {
final room = rooms[i];
return ChatListItem(rooms[i],
key: Key('chat_list_item_${rooms[i].id}'), onTap: () {
// Handle tap on a bot conversation
openChatRoom(room, context);
}, onLongPress: () {
// Handle long press to delete the room
_onChatLongPress(room, context);
});
},
);
}
},
),
);
}

// Method to handle chat tap
void openChatRoom(Room room, BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ChatPage(
roomId: room.id,
)),
);
}

// Method to handle chat long press
void _onChatLongPress(Room room, BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(L10n.of(context)!.leaveTheConvDesc),
actions: <Widget>[
TextButton(
child: Text(L10n.of(context)!.cancel),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text(L10n.of(context)!.leave),
onPressed: () async {
Navigator.of(context).pop();
await showFutureLoadingDialog(
context: context, future: () => _leaveRoom(room));
},
),
],
);
},
);
}

// Method to leave the room
Future<void> _leaveRoom(Room room) async {
final scaffoldMessenger = ScaffoldMessenger.of(context);

try {
await room.leave();
await Future.delayed(
const Duration(seconds: 1)); // Delay to ensure the room is left
// Reload rooms after leaving one
_loadRooms();
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(L10n.of(context)!.leaveTheConvSuccess),
),
);
} catch (e) {
// Log the error
if (kDebugMode) {
print('Error leaving the room: $e');
}
scaffoldMessenger.showSnackBar(
SnackBar(
content:
Text(L10n.of(context)!.tryAgain),
),
);
}
}
}
10 changes: 9 additions & 1 deletion lib/pages/add_bridge/model/social_network.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class WhatsAppResult {
WhatsAppResult(this.result, this.code, this.qrCode);
}

class SocialNetworkManager{
class SocialNetworkManager {
static final List<SocialNetwork> socialNetworks = [
SocialNetwork(
logo: Logo(Logos.facebook_messenger),
Expand Down Expand Up @@ -79,4 +79,12 @@ class SocialNetworkManager{
(network) => network.name == name,
);
}

static bool isBridgeBotId(String? matrixId) {
if (matrixId == null) return false;

return socialNetworks.any(
(network) => matrixId.startsWith(network.chatBot),
);
}
}
Loading

0 comments on commit 86fa322

Please sign in to comment.