Skip to content

Commit

Permalink
Merge pull request #4 from Tawkie/feature-room-bot-can-be-removed-aft…
Browse files Browse the repository at this point in the history
…er-disconnection

Feature room bot can be removed after disconnection
  • Loading branch information
ignyx authored Nov 29, 2023
2 parents 2ecf866 + ad3cae3 commit b848297
Show file tree
Hide file tree
Showing 21 changed files with 1,119 additions and 4 deletions.
8 changes: 8 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ android {
signingConfig signingConfigs.release
}
}

// https://stackoverflow.com/a/77494454/8222484
packagingOptions {
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
}
}

flutter {
Expand Down
24 changes: 23 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2550,5 +2550,27 @@
"editTodo": "Edit todo",
"pleaseAddATitle": "Please add a title",
"todoListChangedError": "Oops... The todo list has been changed while you edited it.",
"todosUnencrypted": "Please notice that todos are visible by everyone in the chat and are not end to end encrypted."
"todosUnencrypted": "Please notice that todos are visible by everyone in the chat and are not end to end encrypted.",
"youDonTHaveConversation": "You don't have any conversation yet.",
"connectChatNetworks": "Connect your chat networks",
"addSocialMessagingAccounts": "Add your social messaging accounts",
"addSocialMessagingAccountsText": "Connect all your conversations!",
"connected": "Connected",
"notConnected": "Not connected",
"connectYourSocialAccount": "Login to your account",
"enterYourDetails": "Enter your details :",
"pleaseEnterPassword": "Please enter your password",
"usernameNotFound": "The username you entered doesn't appear to belong to an account. Please check your username and try again.",
"passwordIncorrect": "Password incorrect",
"rateLimit": "An error has occurred, please wait a few minutes before trying again",
"err_": "Error",
"err_desc": "An error has occurred:",
"err_toConnect": "A problem occurred when connecting to",
"err_timeOut": "A network problem has been detected",
"err_tryAgain": "Please try again",
"bridgeBot_menuItemTitle" : "Connected social networks",
"bridgeBot_deleteConvTitle": "Delete Conversation",
"bridgeBot_deleteConvDescription": "Do you want to delete the conversation with the bot?",
"instagram": "Instagram",
"whatsApp": "WhatsApp"
}
13 changes: 13 additions & 0 deletions lib/config/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import 'package:fluffychat/widgets/layouts/two_column_layout.dart';
import 'package:fluffychat/widgets/log_view.dart';
import 'package:fluffychat/widgets/matrix.dart';

import '../pages/add_bridge/add_bridge_body.dart';

abstract class AppRoutes {
static FutureOr<String?> loggedInRedirect(
BuildContext context,
Expand Down Expand Up @@ -263,6 +265,17 @@ abstract class AppRoutes {
),
],
),

// Route to social networking page via chat bot
// The entire path is: /rooms/settings/addbridgebot
GoRoute(
path: 'addbridgebot',
pageBuilder: (context, state) => defaultPageBuilder(
context,
const AddBridgeBody(),
),
redirect: loggedOutRedirect,
),
GoRoute(
path: 'security',
redirect: loggedOutRedirect,
Expand Down
197 changes: 197 additions & 0 deletions lib/pages/add_bridge/add_bridge_body.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import 'dart:async';

import 'package:fluffychat/pages/add_bridge/service/bot_bridge_connection.dart';
import 'package:fluffychat/pages/add_bridge/service/hostname.dart';
import 'package:fluffychat/pages/add_bridge/show_bottom_sheet.dart';
import 'package:fluffychat/pages/add_bridge/show_delete_conversation_dialog.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/utils/platform_size.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import '../../widgets/matrix.dart';
import 'add_bridge_header.dart';
import 'connection_bridge_dialog.dart';
import 'error_message_dialog.dart';
import 'model/social_network.dart';

// Page offering brigde bot connections to social network chats
class AddBridgeBody extends StatefulWidget {
const AddBridgeBody({
super.key,
});

@override
State<AddBridgeBody> createState() => _AddBridgeBodyState();
}

class _AddBridgeBodyState extends State<AddBridgeBody> {
late BotBridgeConnection botConnection;
late String hostname;
bool timeoutErrorOccurred = false;

@override
void initState() {
final client = Matrix.of(context).client;
String fullUrl = client.homeserver!.host;
hostname = extractHostName(fullUrl);
botConnection = BotBridgeConnection(client: client, hostname: hostname);
super.initState();
_initStateAsync();
}

@override
void dispose() {
botConnection.stopProcess();
super.dispose();
}

// Online status update when page is opened
Future<void> _initStateAsync() async {
try {
final instagramConnected = await botConnection.pingWithTimeout(
context,
botConnection.instagramPing(),
);
if (!mounted) return; // Check if the widget is still mounted

if (instagramConnected != 'error') {
setState(() {
socialNetwork
.firstWhere((element) => element.name == "Instagram")
.connected = instagramConnected == 'Connected' ? true : false;
socialNetwork
.firstWhere((element) => element.name == "Instagram")
.loading = false;
});
} else if (mounted) {
showCatchErrorDialog(
context,
"${L10n.of(context)!.err_toConnect} ${L10n.of(context)!.instagram}",
);
}
} on TimeoutException {
// To indicate that the time-out error has occurred
if (mounted) {
timeoutErrorOccurred = true;
}
} catch (error) {
print("Error pinging Instagram: $error");
await Future.delayed(
const Duration(seconds: 1),
); // Precaution to let the page load
if (mounted && !timeoutErrorOccurred) {
showCatchErrorDialog(
context,
"${L10n.of(context)!.err_toConnect} ${L10n.of(context)!.instagram}",
);
}
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
buildHeaderBridgeText(context),
buildHeaderBridgeSubText(context),
Center(
child: SizedBox(
width: PlatformInfos.isWeb ? PlatformWidth.webWidth : null,
child: ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: socialNetwork.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: socialNetwork[index].logo,
title: Text(
socialNetwork[index].name,
),
// Different build of subtle depending on the social network, for now only Instagram
subtitle: buildSubtitle(socialNetwork[index]),
trailing: const Icon(
CupertinoIcons.right_chevron,
),

// Different ways of connecting and disconnecting depending on the social network
onTap: () =>
handleSocialNetworkAction(socialNetwork[index]),
);
},
),
),
),
],
),
),
);
}

// Different ways of connecting and disconnecting depending on the social network, for now only Instagram
void handleSocialNetworkAction(SocialNetwork network) async {
if (network.loading == false) {
if (network.connected != true) {
bool success = false;
switch (network.name) {
case "Instagram":
// Trying to connect to Instagram
success = await connectToInstagram(context, network, botConnection);
break;

// For other networks
}
if (success) {
setState(() {
network.connected = true;
});
}
} else {
// Disconnect button, for the moment only this choice
final bool success = await showBottomSheetBridge(
context,
network,
botConnection,
);

if (success) {
setState(() {
network.connected = false;
});

// Show the dialog for deleting the conversation
await showDeleteConversationDialog(context, network, botConnection);
} else {
// Display error message to warn user
showCatchErrorDialog(context, L10n.of(context)!.err_timeOut);
}
}
}
}

// Different build of subtle depending on the social network, for now only Instagram
Widget buildSubtitle(SocialNetwork network) {
if (network.loading == true) {
return const Align(
alignment: Alignment.centerLeft,
child: CircularProgressIndicator(
color: Colors.grey,
),
);
} else {
return Text(
network.connected == true
? L10n.of(context)!.connected
: L10n.of(context)!.notConnected,
style: TextStyle(
color: network.connected == true ? Colors.green : Colors.grey,
),
);
}
}
}
30 changes: 30 additions & 0 deletions lib/pages/add_bridge/add_bridge_header.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

// AddBridge page title and subtitle

Widget buildHeaderBridgeText(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
L10n.of(context)!.addSocialMessagingAccounts,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
// color: Color(0xFFFAAB22),
),
),
);
}

Widget buildHeaderBridgeSubText(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
L10n.of(context)!.addSocialMessagingAccountsText,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16.0),
),
);
}
Loading

0 comments on commit b848297

Please sign in to comment.