implement vodozemac (aka steal 50% code from fluffychat)
This commit is contained in:
parent
0c7e9a132e
commit
39b7c99a44
|
|
@ -11,6 +11,8 @@ abstract class AppConfig {
|
||||||
static String? get applicationWelcomeMessage => _applicationWelcomeMessage;
|
static String? get applicationWelcomeMessage => _applicationWelcomeMessage;
|
||||||
static String _defaultHomeserver = 'extera.xyz';
|
static String _defaultHomeserver = 'extera.xyz';
|
||||||
|
|
||||||
|
static bool displayNavigationRail = true;
|
||||||
|
|
||||||
static String get defaultHomeserver => _defaultHomeserver;
|
static String get defaultHomeserver => _defaultHomeserver;
|
||||||
static double fontSizeFactor = 1;
|
static double fontSizeFactor = 1;
|
||||||
static const Color chatColor = primaryColor;
|
static const Color chatColor = primaryColor;
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import 'package:fluffychat/widgets/layouts/two_column_layout.dart';
|
||||||
import 'package:fluffychat/widgets/log_view.dart';
|
import 'package:fluffychat/widgets/log_view.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
import 'package:fluffychat/widgets/share_scaffold_dialog.dart';
|
import 'package:fluffychat/widgets/share_scaffold_dialog.dart';
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
abstract class AppRoutes {
|
abstract class AppRoutes {
|
||||||
static FutureOr<String?> loggedInRedirect(
|
static FutureOr<String?> loggedInRedirect(
|
||||||
|
|
@ -73,7 +74,7 @@ abstract class AppRoutes {
|
||||||
pageBuilder: (context, state) => defaultPageBuilder(
|
pageBuilder: (context, state) => defaultPageBuilder(
|
||||||
context,
|
context,
|
||||||
state,
|
state,
|
||||||
const Login(),
|
Login(client: state.extra as Client),
|
||||||
),
|
),
|
||||||
redirect: loggedInRedirect,
|
redirect: loggedInRedirect,
|
||||||
),
|
),
|
||||||
|
|
@ -260,7 +261,9 @@ abstract class AppRoutes {
|
||||||
pageBuilder: (context, state) => defaultPageBuilder(
|
pageBuilder: (context, state) => defaultPageBuilder(
|
||||||
context,
|
context,
|
||||||
state,
|
state,
|
||||||
const Login(),
|
Login(
|
||||||
|
client: state.extra as Client,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
redirect: loggedOutRedirect,
|
redirect: loggedOutRedirect,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
abstract class SettingKeys {
|
abstract class SettingKeys {
|
||||||
|
static const String displayNavigationRail = 'chat.fluffy.displayNavigationRail';
|
||||||
static const String hideAvatarsInInvites = 'xyz.extera.next.hideAvatarsInInvites';
|
static const String hideAvatarsInInvites = 'xyz.extera.next.hideAvatarsInInvites';
|
||||||
static const String pureBlack = 'xyz.extera.next.pureBlack';
|
static const String pureBlack = 'xyz.extera.next.pureBlack';
|
||||||
static const String renderHtml = 'chat.fluffy.renderHtml';
|
static const String renderHtml = 'chat.fluffy.renderHtml';
|
||||||
|
|
@ -43,6 +44,7 @@ enum AppSettings<T> {
|
||||||
audioRecordingNoiseSuppress<bool>('audioRecordingNoiseSuppress', true),
|
audioRecordingNoiseSuppress<bool>('audioRecordingNoiseSuppress', true),
|
||||||
audioRecordingBitRate<int>('audioRecordingBitRate', 64000),
|
audioRecordingBitRate<int>('audioRecordingBitRate', 64000),
|
||||||
audioRecordingSamplingRate<int>('audioRecordingSamplingRate', 44100),
|
audioRecordingSamplingRate<int>('audioRecordingSamplingRate', 44100),
|
||||||
|
enableSoftLogout<bool>('enableSoftLogout', true),
|
||||||
pushNotificationsGatewayUrl<String>(
|
pushNotificationsGatewayUrl<String>(
|
||||||
'pushNotificationsGatewayUrl',
|
'pushNotificationsGatewayUrl',
|
||||||
'https://push.fluffychat.im/_matrix/push/v1/notify',
|
'https://push.fluffychat.im/_matrix/push/v1/notify',
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod;
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
import 'package:fluffychat/utils/client_manager.dart';
|
import 'package:fluffychat/utils/client_manager.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
|
|
@ -21,6 +23,8 @@ void main() async {
|
||||||
// widget bindings are initialized already.
|
// widget bindings are initialized already.
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
await vod.init(wasmPath: './assets/assets/vodozemac/');
|
||||||
|
|
||||||
Logs().nativeColors = !PlatformInfos.isIOS;
|
Logs().nativeColors = !PlatformInfos.isIOS;
|
||||||
final store = await SharedPreferences.getInstance();
|
final store = await SharedPreferences.getInstance();
|
||||||
final clients = await ClientManager.getClients(store: store);
|
final clients = await ClientManager.getClients(store: store);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:fluffychat/generated/l10n/l10n.dart';
|
|
||||||
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
|
|
@ -69,10 +69,11 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
homeserverController.text.trim().toLowerCase().replaceAll(' ', '-');
|
homeserverController.text.trim().toLowerCase().replaceAll(' ', '-');
|
||||||
|
|
||||||
if (homeserverInput.isEmpty) {
|
if (homeserverInput.isEmpty) {
|
||||||
|
final client = await Matrix.of(context).getLoginClient();
|
||||||
setState(() {
|
setState(() {
|
||||||
error = loginFlows = null;
|
error = loginFlows = null;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
Matrix.of(context).getLoginClient().homeserver = null;
|
client.homeserver = null;
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +89,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
if (homeserver.scheme.isEmpty) {
|
if (homeserver.scheme.isEmpty) {
|
||||||
homeserver = Uri.https(homeserverInput, '');
|
homeserver = Uri.https(homeserverInput, '');
|
||||||
}
|
}
|
||||||
final client = Matrix.of(context).getLoginClient();
|
final client = await Matrix.of(context).getLoginClient();
|
||||||
final (_, _, loginFlows) = await client.checkHomeserver(homeserver);
|
final (_, _, loginFlows) = await client.checkHomeserver(homeserver);
|
||||||
this.loginFlows = loginFlows;
|
this.loginFlows = loginFlows;
|
||||||
if (supportsSso && !legacyPasswordLogin) {
|
if (supportsSso && !legacyPasswordLogin) {
|
||||||
|
|
@ -105,6 +106,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
}
|
}
|
||||||
context.push(
|
context.push(
|
||||||
'${GoRouter.of(context).routeInformationProvider.value.uri.path}/login',
|
'${GoRouter.of(context).routeInformationProvider.value.uri.path}/login',
|
||||||
|
extra: client,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setState(
|
setState(
|
||||||
|
|
@ -142,8 +144,8 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
: isDefaultPlatform
|
: isDefaultPlatform
|
||||||
? '${AppConfig.appOpenUrlScheme.toLowerCase()}://login'
|
? '${AppConfig.appOpenUrlScheme.toLowerCase()}://login'
|
||||||
: 'http://localhost:3001//login';
|
: 'http://localhost:3001//login';
|
||||||
|
final client = await Matrix.of(context).getLoginClient();
|
||||||
final url = Matrix.of(context).getLoginClient().homeserver!.replace(
|
final url = client.homeserver!.replace(
|
||||||
path: '/_matrix/client/v3/login/sso/redirect',
|
path: '/_matrix/client/v3/login/sso/redirect',
|
||||||
queryParameters: {'redirectUrl': redirectUrl},
|
queryParameters: {'redirectUrl': redirectUrl},
|
||||||
);
|
);
|
||||||
|
|
@ -164,11 +166,12 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await Matrix.of(context).getLoginClient().login(
|
final client = await Matrix.of(context).getLoginClient();
|
||||||
LoginType.mLoginToken,
|
client.login(
|
||||||
token: token,
|
LoginType.mLoginToken,
|
||||||
initialDeviceDisplayName: PlatformInfos.clientName,
|
token: token,
|
||||||
);
|
initialDeviceDisplayName: PlatformInfos.clientName,
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setState(() {
|
setState(() {
|
||||||
error = e.toLocalizedString(context);
|
error = e.toLocalizedString(context);
|
||||||
|
|
@ -200,7 +203,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
final client = Matrix.of(context).getLoginClient();
|
final client = await Matrix.of(context).getLoginClient();
|
||||||
await client.importDump(String.fromCharCodes(await file.readAsBytes()));
|
await client.importDump(String.fromCharCodes(await file.readAsBytes()));
|
||||||
Matrix.of(context).initMatrix();
|
Matrix.of(context).initMatrix();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -245,4 +248,4 @@ class IdentityProvider {
|
||||||
icon: json['icon'],
|
icon: json['icon'],
|
||||||
brand: json['brand'],
|
brand: json['brand'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2,9 +2,9 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/generated/l10n/l10n.dart';
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart';
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart';
|
||||||
|
|
@ -14,7 +14,8 @@ import '../../utils/platform_infos.dart';
|
||||||
import 'login_view.dart';
|
import 'login_view.dart';
|
||||||
|
|
||||||
class Login extends StatefulWidget {
|
class Login extends StatefulWidget {
|
||||||
const Login({super.key});
|
final Client client;
|
||||||
|
const Login({required this.client, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
LoginController createState() => LoginController();
|
LoginController createState() => LoginController();
|
||||||
|
|
@ -68,17 +69,18 @@ class LoginController extends State<Login> {
|
||||||
} else {
|
} else {
|
||||||
identifier = AuthenticationUserIdentifier(user: username);
|
identifier = AuthenticationUserIdentifier(user: username);
|
||||||
}
|
}
|
||||||
await matrix.getLoginClient().login(
|
final client = await matrix.getLoginClient();
|
||||||
LoginType.mLoginPassword,
|
await client.login(
|
||||||
identifier: identifier,
|
LoginType.mLoginPassword,
|
||||||
// To stay compatible with older server versions
|
identifier: identifier,
|
||||||
// ignore: deprecated_member_use
|
// To stay compatible with older server versions
|
||||||
user: identifier.type == AuthenticationIdentifierTypes.userId
|
// ignore: deprecated_member_use
|
||||||
? username
|
user: identifier.type == AuthenticationIdentifierTypes.userId
|
||||||
: null,
|
? username
|
||||||
password: passwordController.text,
|
: null,
|
||||||
initialDeviceDisplayName: PlatformInfos.clientName,
|
password: passwordController.text,
|
||||||
);
|
initialDeviceDisplayName: PlatformInfos.clientName,
|
||||||
|
);
|
||||||
} on MatrixException catch (exception) {
|
} on MatrixException catch (exception) {
|
||||||
setState(() => passwordError = exception.errorMessage);
|
setState(() => passwordError = exception.errorMessage);
|
||||||
return setState(() => loading = false);
|
return setState(() => loading = false);
|
||||||
|
|
@ -103,14 +105,13 @@ class LoginController extends State<Login> {
|
||||||
void _checkWellKnown(String userId) async {
|
void _checkWellKnown(String userId) async {
|
||||||
if (mounted) setState(() => usernameError = null);
|
if (mounted) setState(() => usernameError = null);
|
||||||
if (!userId.isValidMatrixId) return;
|
if (!userId.isValidMatrixId) return;
|
||||||
final oldHomeserver = Matrix.of(context).getLoginClient().homeserver;
|
final oldHomeserver = widget.client.homeserver;
|
||||||
try {
|
try {
|
||||||
var newDomain = Uri.https(userId.domain!, '');
|
var newDomain = Uri.https(userId.domain!, '');
|
||||||
Matrix.of(context).getLoginClient().homeserver = newDomain;
|
widget.client.homeserver = newDomain;
|
||||||
DiscoveryInformation? wellKnownInformation;
|
DiscoveryInformation? wellKnownInformation;
|
||||||
try {
|
try {
|
||||||
wellKnownInformation =
|
wellKnownInformation = await widget.client.getWellknown();
|
||||||
await Matrix.of(context).getLoginClient().getWellknown();
|
|
||||||
if (wellKnownInformation.mHomeserver.baseUrl.toString().isNotEmpty) {
|
if (wellKnownInformation.mHomeserver.baseUrl.toString().isNotEmpty) {
|
||||||
newDomain = wellKnownInformation.mHomeserver.baseUrl;
|
newDomain = wellKnownInformation.mHomeserver.baseUrl;
|
||||||
}
|
}
|
||||||
|
|
@ -118,10 +119,10 @@ class LoginController extends State<Login> {
|
||||||
// do nothing, newDomain is already set to a reasonable fallback
|
// do nothing, newDomain is already set to a reasonable fallback
|
||||||
}
|
}
|
||||||
if (newDomain != oldHomeserver) {
|
if (newDomain != oldHomeserver) {
|
||||||
await Matrix.of(context).getLoginClient().checkHomeserver(newDomain);
|
await widget.client.checkHomeserver(newDomain);
|
||||||
|
|
||||||
if (Matrix.of(context).getLoginClient().homeserver == null) {
|
if (widget.client.homeserver == null) {
|
||||||
Matrix.of(context).getLoginClient().homeserver = oldHomeserver;
|
widget.client.homeserver = oldHomeserver;
|
||||||
// okay, the server we checked does not appear to be a matrix server
|
// okay, the server we checked does not appear to be a matrix server
|
||||||
Logs().v(
|
Logs().v(
|
||||||
'$newDomain is not running a homeserver, asking to use $oldHomeserver',
|
'$newDomain is not running a homeserver, asking to use $oldHomeserver',
|
||||||
|
|
@ -144,13 +145,13 @@ class LoginController extends State<Login> {
|
||||||
usernameError = null;
|
usernameError = null;
|
||||||
if (mounted) setState(() {});
|
if (mounted) setState(() {});
|
||||||
} else {
|
} else {
|
||||||
Matrix.of(context).getLoginClient().homeserver = oldHomeserver;
|
widget.client.homeserver = oldHomeserver;
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Matrix.of(context).getLoginClient().homeserver = oldHomeserver;
|
widget.client.homeserver = oldHomeserver;
|
||||||
usernameError = e.toLocalizedString(context);
|
usernameError = e.toLocalizedString(context);
|
||||||
if (mounted) setState(() {});
|
if (mounted) setState(() {});
|
||||||
}
|
}
|
||||||
|
|
@ -173,12 +174,11 @@ class LoginController extends State<Login> {
|
||||||
final clientSecret = DateTime.now().millisecondsSinceEpoch.toString();
|
final clientSecret = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
final response = await showFutureLoadingDialog(
|
final response = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () =>
|
future: () => widget.client.requestTokenToResetPasswordEmail(
|
||||||
Matrix.of(context).getLoginClient().requestTokenToResetPasswordEmail(
|
clientSecret,
|
||||||
clientSecret,
|
input,
|
||||||
input,
|
sendAttempt++,
|
||||||
sendAttempt++,
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
if (response.error != null) return;
|
if (response.error != null) return;
|
||||||
final password = await showTextInputDialog(
|
final password = await showTextInputDialog(
|
||||||
|
|
@ -215,11 +215,11 @@ class LoginController extends State<Login> {
|
||||||
};
|
};
|
||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => Matrix.of(context).getLoginClient().request(
|
future: () => widget.client.request(
|
||||||
RequestType.POST,
|
RequestType.POST,
|
||||||
'/client/v3/account/password',
|
'/client/v3/account/password',
|
||||||
data: data,
|
data: data,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
|
@ -245,4 +245,4 @@ extension on String {
|
||||||
bool get isEmail => _emailRegex.hasMatch(this);
|
bool get isEmail => _emailRegex.hasMatch(this);
|
||||||
|
|
||||||
bool get isPhoneNumber => _phoneRegex.hasMatch(this);
|
bool get isPhoneNumber => _phoneRegex.hasMatch(this);
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/generated/l10n/l10n.dart';
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/widgets/layouts/login_scaffold.dart';
|
import 'package:fluffychat/widgets/layouts/login_scaffold.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
import 'login.dart';
|
import 'login.dart';
|
||||||
|
|
@ -15,16 +14,15 @@ class LoginView extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
final homeserver = Matrix.of(context)
|
final homeserver = controller.widget.client.homeserver
|
||||||
.getLoginClient()
|
|
||||||
.homeserver
|
|
||||||
.toString()
|
.toString()
|
||||||
.replaceFirst('https://', '');
|
.replaceFirst('https://', '');
|
||||||
final title = L10n.of(context).logInTo(homeserver);
|
final title = L10n.of(context).logInTo(homeserver);
|
||||||
final titleParts = title.split(homeserver);
|
final titleParts = title.split(homeserver);
|
||||||
|
|
||||||
return LoginScaffold(
|
return LoginScaffold(
|
||||||
enforceMobileMode: Matrix.of(context).client.isLogged(),
|
enforceMobileMode:
|
||||||
|
Matrix.of(context).widget.clients.any((client) => client.isLogged()),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: controller.loading ? null : const Center(child: BackButton()),
|
leading: controller.loading ? null : const Center(child: BackButton()),
|
||||||
automaticallyImplyLeading: !controller.loading,
|
automaticallyImplyLeading: !controller.loading,
|
||||||
|
|
@ -140,4 +138,4 @@ class LoginView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:desktop_notifications/desktop_notifications.dart';
|
import 'package:desktop_notifications/desktop_notifications.dart';
|
||||||
import 'package:fluffychat/generated/l10n/l10n.dart';
|
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod;
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:matrix/encryption/utils/key_verification.dart';
|
import 'package:matrix/encryption/utils/key_verification.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
@ -46,7 +47,7 @@ abstract class ClientManager {
|
||||||
await store.setStringList(clientNamespace, clientNames.toList());
|
await store.setStringList(clientNamespace, clientNames.toList());
|
||||||
}
|
}
|
||||||
final clients =
|
final clients =
|
||||||
clientNames.map((name) => createClient(name, store)).toList();
|
await Future.wait(clientNames.map((name) => createClient(name, store)));
|
||||||
if (initialize) {
|
if (initialize) {
|
||||||
await Future.wait(
|
await Future.wait(
|
||||||
clients.map(
|
clients.map(
|
||||||
|
|
@ -98,10 +99,17 @@ abstract class ClientManager {
|
||||||
|
|
||||||
static NativeImplementations get nativeImplementations => kIsWeb
|
static NativeImplementations get nativeImplementations => kIsWeb
|
||||||
? const NativeImplementationsDummy()
|
? const NativeImplementationsDummy()
|
||||||
: NativeImplementationsIsolate(compute);
|
: NativeImplementationsIsolate(
|
||||||
|
compute,
|
||||||
|
vodozemacInit: () => vod.init(wasmPath: './assets/assets/vodozemac/'),
|
||||||
|
);
|
||||||
|
|
||||||
static Client createClient(String clientName, SharedPreferences store) {
|
static Future<Client> createClient(
|
||||||
|
String clientName,
|
||||||
|
SharedPreferences store,
|
||||||
|
) async {
|
||||||
final shareKeysWith = AppSettings.shareKeysWith.getItem(store);
|
final shareKeysWith = AppSettings.shareKeysWith.getItem(store);
|
||||||
|
final enableSoftLogout = AppSettings.enableSoftLogout.getItem(store);
|
||||||
|
|
||||||
return Client(
|
return Client(
|
||||||
clientName,
|
clientName,
|
||||||
|
|
@ -117,8 +125,7 @@ abstract class ClientManager {
|
||||||
'im.ponies.room_emotes',
|
'im.ponies.room_emotes',
|
||||||
},
|
},
|
||||||
logLevel: kReleaseMode ? Level.warning : Level.verbose,
|
logLevel: kReleaseMode ? Level.warning : Level.verbose,
|
||||||
//database: flutterMatrixSdkDatabaseBuilder(client),
|
database: await flutterMatrixSdkDatabaseBuilder(clientName),
|
||||||
databaseBuilder: flutterMatrixSdkDatabaseBuilder,
|
|
||||||
supportedLoginTypes: {
|
supportedLoginTypes: {
|
||||||
AuthenticationTypes.password,
|
AuthenticationTypes.password,
|
||||||
AuthenticationTypes.sso,
|
AuthenticationTypes.sso,
|
||||||
|
|
@ -131,6 +138,8 @@ abstract class ClientManager {
|
||||||
.singleWhereOrNull((share) => share.name == shareKeysWith) ??
|
.singleWhereOrNull((share) => share.name == shareKeysWith) ??
|
||||||
ShareKeysWith.all,
|
ShareKeysWith.all,
|
||||||
convertLinebreaksInFormatting: false,
|
convertLinebreaksInFormatting: false,
|
||||||
|
onSoftLogout:
|
||||||
|
enableSoftLogout ? (client) => client.refreshAccessToken() : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,4 +187,4 @@ abstract class ClientManager {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/generated/l10n/l10n.dart';
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
@ -10,6 +10,7 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
import 'package:universal_html/html.dart' as html;
|
import 'package:universal_html/html.dart' as html;
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
import 'package:fluffychat/utils/client_manager.dart';
|
import 'package:fluffychat/utils/client_manager.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
import 'cipher.dart';
|
import 'cipher.dart';
|
||||||
|
|
@ -17,10 +18,10 @@ import 'cipher.dart';
|
||||||
import 'sqlcipher_stub.dart'
|
import 'sqlcipher_stub.dart'
|
||||||
if (dart.library.io) 'package:sqlcipher_flutter_libs/sqlcipher_flutter_libs.dart';
|
if (dart.library.io) 'package:sqlcipher_flutter_libs/sqlcipher_flutter_libs.dart';
|
||||||
|
|
||||||
Future<DatabaseApi> flutterMatrixSdkDatabaseBuilder(Client client) async {
|
Future<DatabaseApi> flutterMatrixSdkDatabaseBuilder(String clientName) async {
|
||||||
MatrixSdkDatabase? database;
|
MatrixSdkDatabase? database;
|
||||||
try {
|
try {
|
||||||
database = await _constructDatabase(client);
|
database = await _constructDatabase(clientName);
|
||||||
await database.open();
|
await database.open();
|
||||||
return database;
|
return database;
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
|
|
@ -36,7 +37,7 @@ Future<DatabaseApi> flutterMatrixSdkDatabaseBuilder(Client client) async {
|
||||||
|
|
||||||
// Delete database file:
|
// Delete database file:
|
||||||
if (database == null && !kIsWeb) {
|
if (database == null && !kIsWeb) {
|
||||||
final dbFile = File(await _getDatabasePath(client.clientName));
|
final dbFile = File(await _getDatabasePath(clientName));
|
||||||
if (await dbFile.exists()) await dbFile.delete();
|
if (await dbFile.exists()) await dbFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,16 +55,14 @@ Future<DatabaseApi> flutterMatrixSdkDatabaseBuilder(Client client) async {
|
||||||
Logs().e('Unable to send error notification', e, s);
|
Logs().e('Unable to send error notification', e, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
database = await _constructDatabase(client);
|
rethrow;
|
||||||
await database.open();
|
|
||||||
return database;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MatrixSdkDatabase> _constructDatabase(Client client) async {
|
Future<MatrixSdkDatabase> _constructDatabase(String clientName) async {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
html.window.navigator.storage?.persist();
|
html.window.navigator.storage?.persist();
|
||||||
return MatrixSdkDatabase(client.clientName);
|
return await MatrixSdkDatabase.init(clientName);
|
||||||
}
|
}
|
||||||
|
|
||||||
final cipher = await getDatabaseCipher();
|
final cipher = await getDatabaseCipher();
|
||||||
|
|
@ -77,7 +76,7 @@ Future<MatrixSdkDatabase> _constructDatabase(Client client) async {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final path = await _getDatabasePath(client.clientName);
|
final path = await _getDatabasePath(clientName);
|
||||||
|
|
||||||
// fix dlopen for old Android
|
// fix dlopen for old Android
|
||||||
await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions();
|
await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions();
|
||||||
|
|
@ -86,7 +85,7 @@ Future<MatrixSdkDatabase> _constructDatabase(Client client) async {
|
||||||
createDatabaseFactoryFfi(ffiInit: SQfLiteEncryptionHelper.ffiInit);
|
createDatabaseFactoryFfi(ffiInit: SQfLiteEncryptionHelper.ffiInit);
|
||||||
|
|
||||||
// migrate from potential previous SQLite database path to current one
|
// migrate from potential previous SQLite database path to current one
|
||||||
await _migrateLegacyLocation(path, client.clientName);
|
await _migrateLegacyLocation(path, clientName);
|
||||||
|
|
||||||
// required for [getDatabasesPath]
|
// required for [getDatabasesPath]
|
||||||
databaseFactory = factory;
|
databaseFactory = factory;
|
||||||
|
|
@ -113,8 +112,8 @@ Future<MatrixSdkDatabase> _constructDatabase(Client client) async {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return MatrixSdkDatabase(
|
return await MatrixSdkDatabase.init(
|
||||||
client.clientName,
|
clientName,
|
||||||
database: database,
|
database: database,
|
||||||
maxFileSize: 1000 * 1000 * 10,
|
maxFileSize: 1000 * 1000 * 10,
|
||||||
fileStorageLocation: fileStorageLocation?.uri,
|
fileStorageLocation: fileStorageLocation?.uri,
|
||||||
|
|
@ -149,4 +148,4 @@ Future<void> _migrateLegacyLocation(
|
||||||
await maybeOldFile.copy(sqlFilePath);
|
await maybeOldFile.copy(sqlFilePath);
|
||||||
await maybeOldFile.delete();
|
await maybeOldFile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,10 +6,10 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:desktop_notifications/desktop_notifications.dart';
|
import 'package:desktop_notifications/desktop_notifications.dart';
|
||||||
import 'package:fluffychat/generated/l10n/l10n.dart';
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:just_audio/just_audio.dart';
|
||||||
import 'package:matrix/encryption.dart';
|
import 'package:matrix/encryption.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
@ -17,6 +17,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:universal_html/html.dart' as html;
|
import 'package:universal_html/html.dart' as html;
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/generated/l10n/l10n.dart';
|
||||||
import 'package:fluffychat/utils/client_manager.dart';
|
import 'package:fluffychat/utils/client_manager.dart';
|
||||||
import 'package:fluffychat/utils/init_with_restore.dart';
|
import 'package:fluffychat/utils/init_with_restore.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart';
|
||||||
|
|
@ -73,9 +74,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||||
BackgroundPush? backgroundPush;
|
BackgroundPush? backgroundPush;
|
||||||
|
|
||||||
Client get client {
|
Client get client {
|
||||||
if (widget.clients.isEmpty) {
|
|
||||||
widget.clients.add(getLoginClient());
|
|
||||||
}
|
|
||||||
if (_activeClient < 0 || _activeClient >= widget.clients.length) {
|
if (_activeClient < 0 || _activeClient >= widget.clients.length) {
|
||||||
return currentBundle!.first!;
|
return currentBundle!.first!;
|
||||||
}
|
}
|
||||||
|
|
@ -148,29 +146,35 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||||
|
|
||||||
Client? _loginClientCandidate;
|
Client? _loginClientCandidate;
|
||||||
|
|
||||||
Client getLoginClient() {
|
AudioPlayer? audioPlayer;
|
||||||
|
final ValueNotifier<String?> voiceMessageEventId = ValueNotifier(null);
|
||||||
|
|
||||||
|
Future<Client> getLoginClient() async {
|
||||||
if (widget.clients.isNotEmpty && !client.isLogged()) {
|
if (widget.clients.isNotEmpty && !client.isLogged()) {
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
final candidate = _loginClientCandidate ??= ClientManager.createClient(
|
final candidate =
|
||||||
|
_loginClientCandidate ??= await ClientManager.createClient(
|
||||||
'${AppConfig.applicationName}-${DateTime.now().millisecondsSinceEpoch}',
|
'${AppConfig.applicationName}-${DateTime.now().millisecondsSinceEpoch}',
|
||||||
store,
|
store,
|
||||||
)..onLoginStateChanged
|
)
|
||||||
.stream
|
..onLoginStateChanged
|
||||||
.where((l) => l == LoginState.loggedIn)
|
.stream
|
||||||
.first
|
.where((l) => l == LoginState.loggedIn)
|
||||||
.then((_) {
|
.first
|
||||||
if (!widget.clients.contains(_loginClientCandidate)) {
|
.then((_) {
|
||||||
widget.clients.add(_loginClientCandidate!);
|
if (!widget.clients.contains(_loginClientCandidate)) {
|
||||||
}
|
widget.clients.add(_loginClientCandidate!);
|
||||||
ClientManager.addClientNameToStore(
|
}
|
||||||
_loginClientCandidate!.clientName,
|
ClientManager.addClientNameToStore(
|
||||||
store,
|
_loginClientCandidate!.clientName,
|
||||||
);
|
store,
|
||||||
_registerSubs(_loginClientCandidate!.clientName);
|
);
|
||||||
_loginClientCandidate = null;
|
_registerSubs(_loginClientCandidate!.clientName);
|
||||||
FluffyChatApp.router.go('/rooms');
|
_loginClientCandidate = null;
|
||||||
});
|
FluffyChatApp.router.go('/rooms');
|
||||||
|
});
|
||||||
|
if (widget.clients.isEmpty) widget.clients.add(candidate);
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,12 +283,12 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||||
onLoginStateChanged[name] ??= c.onLoginStateChanged.stream.listen((state) {
|
onLoginStateChanged[name] ??= c.onLoginStateChanged.stream.listen((state) {
|
||||||
final loggedInWithMultipleClients = widget.clients.length > 1;
|
final loggedInWithMultipleClients = widget.clients.length > 1;
|
||||||
if (state == LoginState.loggedOut) {
|
if (state == LoginState.loggedOut) {
|
||||||
InitWithRestoreExtension.deleteSessionBackup(name);
|
|
||||||
}
|
|
||||||
if (loggedInWithMultipleClients && state != LoginState.loggedIn) {
|
|
||||||
_cancelSubs(c.clientName);
|
_cancelSubs(c.clientName);
|
||||||
widget.clients.remove(c);
|
widget.clients.remove(c);
|
||||||
ClientManager.removeClientNameFromStore(c.clientName, store);
|
ClientManager.removeClientNameFromStore(c.clientName, store);
|
||||||
|
InitWithRestoreExtension.deleteSessionBackup(name);
|
||||||
|
}
|
||||||
|
if (loggedInWithMultipleClients && state != LoginState.loggedIn) {
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(
|
||||||
FluffyChatApp.router.routerDelegate.navigatorKey.currentContext ??
|
FluffyChatApp.router.routerDelegate.navigatorKey.currentContext ??
|
||||||
context,
|
context,
|
||||||
|
|
@ -376,12 +380,14 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||||
Logs().v('AppLifecycleState = $state');
|
Logs().v('AppLifecycleState = $state');
|
||||||
final foreground = state != AppLifecycleState.inactive &&
|
final foreground = state != AppLifecycleState.inactive &&
|
||||||
state != AppLifecycleState.paused;
|
state != AppLifecycleState.paused;
|
||||||
client.syncPresence =
|
for (final client in widget.clients) {
|
||||||
state == AppLifecycleState.resumed ? null : PresenceType.unavailable;
|
client.syncPresence =
|
||||||
if (PlatformInfos.isMobile) {
|
state == AppLifecycleState.resumed ? null : PresenceType.unavailable;
|
||||||
client.backgroundSync = foreground;
|
if (PlatformInfos.isMobile) {
|
||||||
client.requestHistoryOnLimitedTimeline = !foreground;
|
client.backgroundSync = foreground;
|
||||||
Logs().v('Set background sync to', foreground);
|
client.requestHistoryOnLimitedTimeline = !foreground;
|
||||||
|
Logs().v('Set background sync to', foreground);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -432,6 +438,10 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||||
|
|
||||||
AppConfig.showPresences =
|
AppConfig.showPresences =
|
||||||
store.getBool(SettingKeys.showPresences) ?? AppConfig.showPresences;
|
store.getBool(SettingKeys.showPresences) ?? AppConfig.showPresences;
|
||||||
|
|
||||||
|
AppConfig.displayNavigationRail =
|
||||||
|
store.getBool(SettingKeys.displayNavigationRail) ??
|
||||||
|
AppConfig.displayNavigationRail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -493,4 +503,4 @@ class _AccountBundleWithClient {
|
||||||
final AccountBundle? bundle;
|
final AccountBundle? bundle;
|
||||||
|
|
||||||
_AccountBundleWithClient({this.client, this.bundle});
|
_AccountBundleWithClient({this.client, this.bundle});
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
flutter_vodozemac
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
|
||||||
57
pubspec.lock
57
pubspec.lock
|
|
@ -137,6 +137,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
build_cli_annotations:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_cli_annotations
|
||||||
|
sha256: b59d2769769efd6c9ff6d4c4cede0be115a566afc591705c2040b707534b1172
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
canonical_json:
|
canonical_json:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -608,14 +616,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
flutter_olm:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_olm
|
|
||||||
sha256: "5e6211af8cba1abf7d1f92e543f6d573dfe6017fe4742e0d04ba84beab47f940"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
flutter_openssl_crypto:
|
flutter_openssl_crypto:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -632,6 +632,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.28"
|
version: "2.0.28"
|
||||||
|
flutter_rust_bridge:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_rust_bridge
|
||||||
|
sha256: b416ff56002789e636244fb4cc449f587656eff995e5a7169457eb0593fcaddb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.10.0"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -702,6 +710,14 @@ packages:
|
||||||
url: "https://github.com/famedly/flutter_typeahead.git"
|
url: "https://github.com/famedly/flutter_typeahead.git"
|
||||||
source: git
|
source: git
|
||||||
version: "5.2.0"
|
version: "5.2.0"
|
||||||
|
flutter_vodozemac:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_vodozemac
|
||||||
|
sha256: "2405ca121b84d1cd83200a14021022e1691b123a23bcefc36adc7740cefbc1f9"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.2"
|
||||||
flutter_web_auth_2:
|
flutter_web_auth_2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -1153,10 +1169,11 @@ packages:
|
||||||
matrix:
|
matrix:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "../matrix-dart-sdk"
|
name: matrix
|
||||||
relative: true
|
sha256: "127cc89a030e1555fc02c3434f443feca942320af6248122b36c56448e59fb19"
|
||||||
source: path
|
url: "https://pub.dev"
|
||||||
version: "0.40.0"
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -1213,14 +1230,6 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.2"
|
||||||
olm:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: olm
|
|
||||||
sha256: "6a3fe1e5170b954dd9e4ba3b27513e6aa9b7591eb7bb0d7f6f32140b7f140c6f"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0"
|
|
||||||
opus_caf_converter_dart:
|
opus_caf_converter_dart:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -2194,6 +2203,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.0.0"
|
version: "15.0.0"
|
||||||
|
vodozemac:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: vodozemac
|
||||||
|
sha256: dba14017e042748fb22d270e8ab1d3e46965b89788dd3857dba938ec07571968
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
wakelock_plus:
|
wakelock_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,15 @@ dependencies:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_map: ^6.1.0
|
flutter_map: ^6.1.0
|
||||||
flutter_new_badger: ^1.1.1
|
flutter_new_badger: ^1.1.1
|
||||||
flutter_olm: 2.0.0
|
|
||||||
flutter_openssl_crypto: ^0.5.0
|
flutter_openssl_crypto: ^0.5.0
|
||||||
|
flutter_rust_bridge: ^2.10.0
|
||||||
flutter_secure_storage: ^9.2.2
|
flutter_secure_storage: ^9.2.2
|
||||||
flutter_shortcuts_new: ^2.0.0
|
flutter_shortcuts_new: ^2.0.0
|
||||||
flutter_typeahead: ## Custom fork from flutter_typeahead since the package is not maintain well.
|
flutter_typeahead: ## Custom fork from flutter_typeahead since the package is not maintain well.
|
||||||
git:
|
git:
|
||||||
url: https://github.com/famedly/flutter_typeahead.git
|
url: https://github.com/famedly/flutter_typeahead.git
|
||||||
ref: main
|
ref: main
|
||||||
|
flutter_vodozemac: ^0.2.2
|
||||||
flutter_web_auth_2: ^3.1.1 # Version 4 blocked by https://github.com/MixinNetwork/flutter-plugins/issues/379
|
flutter_web_auth_2: ^3.1.1 # Version 4 blocked by https://github.com/MixinNetwork/flutter-plugins/issues/379
|
||||||
flutter_webrtc: ^0.12.9
|
flutter_webrtc: ^0.12.9
|
||||||
geolocator: ^13.0.1
|
geolocator: ^13.0.1
|
||||||
|
|
@ -62,8 +63,7 @@ dependencies:
|
||||||
latlong2: ^0.9.1
|
latlong2: ^0.9.1
|
||||||
linkify: ^5.0.0
|
linkify: ^5.0.0
|
||||||
material: ^1.0.0+2
|
material: ^1.0.0+2
|
||||||
matrix:
|
matrix: ^1.0.0
|
||||||
path: ../matrix-dart-sdk
|
|
||||||
mime: ^1.0.6
|
mime: ^1.0.6
|
||||||
native_imaging: ^0.2.0
|
native_imaging: ^0.2.0
|
||||||
opus_caf_converter_dart: ^1.0.1
|
opus_caf_converter_dart: ^1.0.1
|
||||||
|
|
@ -93,6 +93,7 @@ dependencies:
|
||||||
url_launcher: ^6.2.5
|
url_launcher: ^6.2.5
|
||||||
video_compress: ^3.1.4
|
video_compress: ^3.1.4
|
||||||
video_player: ^2.9.2
|
video_player: ^2.9.2
|
||||||
|
vodozemac: ^0.2.0
|
||||||
wakelock_plus: ^1.2.2
|
wakelock_plus: ^1.2.2
|
||||||
webrtc_interface: ^1.0.13
|
webrtc_interface: ^1.0.13
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
flutter_vodozemac
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue