Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature beta group #35

Merged
merged 19 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2682,5 +2682,22 @@
"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.",
"joinBetaTitle": "Join the Beta",
"betaJoinExplanation": "## How to test the Beta version and access new features in advance?",
"betaJoinBenefit": "Participating in the Beta allows you to access application updates in advance and be the first to test new features!",
"iosInstructionsTitle": "On iOS:",
"installTestflight": "- Install Apple Testflight",
"downloadTestflightButton": "Download Apple Testflight",
"joinBetaTitleIOS": "- Join the Beta",
"downloadBetaIOSButton": "Download the iOS Beta",
"joinBetaGroup": "- Join the Tawkie Beta group: #beta",
"androidInstructionsTitle": "On Android:",
"joinBetaPlayStore": "- Join the Beta from the Play Store or online",
"downloadBetaAndroidButton": "Download the Android Beta",
"joinBetaButtonLabel": "Join the Beta group",
"joinBetaError": "Something went wrong: ",
"failedToJoinRoom": "Failed to join room: ",
"roomIdNullError": "Room ID is null for alias: ",
"roomNotFoundError": "Room not found after joining"
}
19 changes: 18 additions & 1 deletion assets/l10n/intl_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2498,5 +2498,22 @@
"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.",
"joinBetaTitle": "Rejoindre la Bêta",
ignyx marked this conversation as resolved.
Show resolved Hide resolved
"betaJoinExplanation": "## Comment tester la version Beta et accéder aux nouvelles fonctionnalités en avance ?",
"betaJoinBenefit": "Participer à la Beta permet d'avoir accès aux mises à jour de l'application en avance et tester en premier.ère les nouvelles fonctionnalités !",
"iosInstructionsTitle": "Sous iOS :",
"installTestflight": "- Installer Apple Testflight",
"downloadTestflightButton": "Télécharger Apple Testflight",
"joinBetaTitleIOS": "- Rejoindre la Beta",
"downloadBetaIOSButton": "Télécharger la Beta iOS",
"joinBetaGroup": "- Rejoindre le groupe Tawkie de la Beta : #beta",
"androidInstructionsTitle": "Sous Android :",
"joinBetaPlayStore": "- Rejoindre la Beta depuis le Play Store ou en ligne",
"downloadBetaAndroidButton": "Télécharger la Beta Android",
"joinBetaButtonLabel": "Rejoindre le groupe Beta",
"joinBetaError": "Une erreur s'est produite : ",
"failedToJoinRoom": "Échec de la connexion à la salle : ",
"roomIdNullError": "L'ID de la salle est nul pour l'alias : ",
"roomNotFoundError": "Salle introuvable après la connexion"
}
17 changes: 17 additions & 0 deletions lib/config/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,23 @@ abstract class AppConfig {
static const String baseUrl = kDebugMode ? stagingUrl : productionUrl;
static String tawkieSubscriptionIdentifier = 'Tawkie subscription';

// URLs for Beta Join
static const String testflightAppUrl = 'https://apps.apple.com/us/app/testflight/id899247664';
static const String appleBetaUrl = 'https://testflight.apple.com/join/daXe0NfW';
static const String playStoreUrl = 'https://play.google.com/store/apps/details?id=fr.tawkie.app';
static const String androidBetaUrl = 'https://play.google.com/apps/testing/fr.tawkie.app';

static const String iosUrl = 'itms-apps://itunes.apple.com/app/id899247664';
static const String androidUrl = 'market://details?id=fr.tawkie.app';

static const String prodBetaAlias = 'beta';
static const String testBetaAlias = 'testbeta';
static const String betaAlias = kDebugMode ? testBetaAlias : prodBetaAlias;
static const String serverStagingUrl = ':staging.tawkie.fr';
static const String serverProductionUrl = ':alpha.tawkie.fr';
static const String server = kDebugMode ? serverStagingUrl : serverProductionUrl;
static const String roomAlias = '#$betaAlias$server';

static void loadFromJson(Map<String, dynamic> json) {
if (json['chat_color'] != null) {
try {
Expand Down
16 changes: 12 additions & 4 deletions lib/config/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import 'package:go_router/go_router.dart';

import 'package:tawkie/config/themes.dart';
import 'package:tawkie/pages/add_bridge/add_bridge.dart';
import 'package:tawkie/pages/add_bridge/add_bridge_body.dart';
import 'package:tawkie/pages/archive/archive.dart';
import 'package:tawkie/pages/auth/auth.dart';
import 'package:tawkie/pages/beta/beta.dart';
import 'package:tawkie/pages/chat/chat.dart';
import 'package:tawkie/pages/chat_access_settings/chat_access_settings_controller.dart';
import 'package:tawkie/pages/chat_details/chat_details.dart';
Expand Down Expand Up @@ -49,7 +47,8 @@ abstract class AppRoutes {
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
final sessionToken = await _secureStorage.read(key: 'sessionToken');

final bool isLoggedKratos = sessionToken is String && sessionToken.isNotEmpty;
final bool isLoggedKratos =
sessionToken is String && sessionToken.isNotEmpty;
final bool isLoggedMatrix = Matrix.of(context).client.isLogged();
final bool preAuth = state.fullPath!.startsWith('/home');

Expand Down Expand Up @@ -306,6 +305,15 @@ abstract class AppRoutes {
),
],
),
GoRoute(
path: 'joinBeta',
pageBuilder: (context, state) => defaultPageBuilder(
context,
state,
const BetaJoinPage(),
),
redirect: loggedOutRedirect,
),
// Route to social networking page via chat bot
// The entire path is: /rooms/settings/addbridgebot
GoRoute(
Expand Down
242 changes: 242 additions & 0 deletions lib/pages/beta/beta.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import 'dart:io' show Platform;

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:go_router/go_router.dart';
import 'package:matrix/matrix.dart';
import 'package:tawkie/config/app_config.dart';
import 'package:tawkie/widgets/matrix.dart';
import 'package:url_launcher/url_launcher.dart';

class BetaJoinPage extends StatelessWidget {
const BetaJoinPage({super.key});

void joinBeta() async {
try {
if (Platform.isIOS) {
if (await canLaunchUrl(Uri.parse(AppConfig.iosUrl))) {
await launchUrl(Uri.parse(AppConfig.iosUrl));
} else {
await _launchUrlOrThrow(AppConfig.appleBetaUrl);
}
} else if (Platform.isAndroid) {
if (await canLaunchUrl(Uri.parse(AppConfig.androidUrl))) {
await launchUrl(Uri.parse(AppConfig.androidUrl));
} else {
await _launchUrlOrThrow(AppConfig.androidBetaUrl);
}
}
} catch (e) {
if (kDebugMode) {
print('Error launching URL: $e');
}
}
}

Future<void> _launchUrlOrThrow(String url) async {
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
} else {
throw 'Could not launch $url';
}
}

Future<void> joinGroup({
required BuildContext context,
}) async {
final client = Matrix.of(context).client;
const String roomAlias = AppConfig.roomAlias;

try {
if (kDebugMode) {
print('Attempting to join room: $roomAlias');
}

// Get room ID from alias
final roomAliasResult = await client.getRoomIdByAlias(roomAlias);
final roomId = roomAliasResult.roomId;

if (roomId == null) {
final errorMsg = L10n.of(context)!.failedToJoinRoom +
L10n.of(context)!.roomIdNullError +
roomAlias;
if (kDebugMode) {
print(errorMsg);
}
throw Exception(errorMsg);
}

// Check if the user is already a member of the room
final room = client.getRoomById(roomId);
if (room != null && room.membership == Membership.join) {
// Navigate directly to the room
context.go('/rooms/$roomId');
return;
}

final result = await showFutureLoadingDialog<String>(
context: context,
future: () async {
try {
// Retrieve participating servers
final servers = roomAliasResult.servers ?? ['staging.tawkie.fr'];
ignyx marked this conversation as resolved.
Show resolved Hide resolved
final waitForRoom = client.waitForRoomInSync(roomId, join: true);

await client.joinRoom(roomId, serverName: servers);
await waitForRoom;

return roomId;
} catch (e) {
final errorMsg = L10n.of(context)!.failedToJoinRoom + e.toString();
if (kDebugMode) {
print(errorMsg);
}
throw Exception(errorMsg);
}
},
);

if (result.error == null) {
Navigator.of(context).pop();

final joinedRoom = client.getRoomById(result.result!);
if (joinedRoom == null) {
final errorMsg = L10n.of(context)!.failedToJoinRoom +
L10n.of(context)!.roomNotFoundError;
if (kDebugMode) {
print(errorMsg);
}
throw Exception(errorMsg);
}

// Navigate to the room
context.go('/rooms/${result.result!}');
} else {
final errorMsg =
L10n.of(context)!.failedToJoinRoom + result.error.toString();
if (kDebugMode) {
print(errorMsg);
}
final snackBar = SnackBar(content: Text(errorMsg));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
} catch (e) {
final errorMsg = L10n.of(context)!.joinBetaError + e.toString();
if (kDebugMode) {
print(errorMsg);
}
final snackBar = SnackBar(content: Text(errorMsg));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(L10n.of(context)!.joinBetaTitle),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: [
Text(
L10n.of(context)!.betaJoinExplanation,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20.0),
Text(
L10n.of(context)!.betaJoinBenefit,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 20.0),
if (Platform.isIOS) _buildIOSInstructions(context),
if (Platform.isAndroid) _buildAndroidInstructions(context),
const SizedBox(height: 10.0),
ElevatedButton.icon(
onPressed: () async {
await joinGroup(context: context);
},
icon: const Icon(Icons.new_releases),
label: Text(L10n.of(context)!.joinBetaButtonLabel),
),
],
),
),
);
}

Widget _buildIOSInstructions(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
L10n.of(context)!.iosInstructionsTitle,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
L10n.of(context)!.installTestflight,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: () async {
await _launchUrlOrThrow(AppConfig.testflightAppUrl);
},
child: Text(L10n.of(context)!.downloadTestflightButton),
),
const Divider(thickness: 1),
Text(
L10n.of(context)!.joinBetaTitleIOS,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: () async {
await _launchUrlOrThrow(AppConfig.appleBetaUrl);
},
child: Text(L10n.of(context)!.downloadBetaIOSButton),
),
const Divider(thickness: 1),
Text(
L10n.of(context)!.joinBetaGroup,
style: const TextStyle(fontSize: 16),
),
],
);
}

Widget _buildAndroidInstructions(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
L10n.of(context)!.androidInstructionsTitle,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
L10n.of(context)!.joinBetaPlayStore,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: () async {
try {
await _launchUrlOrThrow(AppConfig.playStoreUrl);
} catch (e) {
await _launchUrlOrThrow(AppConfig.androidBetaUrl);
ignyx marked this conversation as resolved.
Show resolved Hide resolved
}
},
child: Text(L10n.of(context)!.downloadBetaAndroidButton),
),
const Divider(thickness: 1),
Text(
L10n.of(context)!.joinBetaGroup,
style: const TextStyle(fontSize: 16),
),
],
);
}
}
Loading
Loading