This commit is contained in:
OfficialDakari 2025-11-19 18:39:07 +05:00
commit ae014ad40b
17 changed files with 269 additions and 289 deletions

View File

@ -3,6 +3,9 @@ import 'dart:ui';
import 'package:matrix/matrix.dart';
abstract class AppConfig {
static const String pushIsolatePortName = 'push_isolate';
static const String mainIsolatePortName = 'main_isolate';
static String _applicationName = 'Extera';
static String get applicationName => _applicationName;

View File

@ -1,3 +1,6 @@
import 'dart:isolate';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
@ -15,9 +18,20 @@ import 'config/setting_keys.dart';
import 'utils/background_push.dart';
import 'widgets/fluffy_chat_app.dart';
ReceivePort? mainIsolateReceivePort;
void main() async {
Logs().i('Welcome to ${AppConfig.applicationName} <3');
if (PlatformInfos.isAndroid) {
final port = mainIsolateReceivePort = ReceivePort();
IsolateNameServer.removePortNameMapping('main_isolate');
IsolateNameServer.registerPortWithName(
port.sendPort,
'main_isolate',
);
}
// Our background push shared isolate accesses flutter-internal things very early in the startup proccess
// To make sure that the parts of flutter needed are started up already, we need to ensure that the
// widget bindings are initialized already.

View File

@ -34,7 +34,6 @@ class RecordingViewModelState extends State<RecordingViewModel> {
Timer? _recorderSubscription;
Duration duration = Duration.zero;
bool error = false;
bool isSending = false;
bool get isRecording => _audioRecorder != null;
@ -88,7 +87,11 @@ class RecordingViewModelState extends State<RecordingViewModel> {
final result = await audioRecorder.hasPermission();
if (result != true) {
setState(() => error = true);
showOkAlertDialog(
context: context,
title: L10n.of(context).oopsSomethingWentWrong,
message: L10n.of(context).noPermission,
);
return;
}
await WakelockPlus.enable();
@ -107,9 +110,14 @@ class RecordingViewModelState extends State<RecordingViewModel> {
);
setState(() => duration = Duration.zero);
_subscribe();
} catch (_) {
setState(() => error = true);
rethrow;
} catch (e, s) {
Logs().w('Unable to start voice message recording', e, s);
showOkAlertDialog(
context: context,
title: L10n.of(context).oopsSomethingWentWrong,
message: e.toString(),
);
setState(_reset);
}
}
@ -139,7 +147,6 @@ class RecordingViewModelState extends State<RecordingViewModel> {
_audioRecorder?.stop();
_audioRecorder = null;
isSending = false;
error = false;
fileName = null;
duration = Duration.zero;
amplitudeTimeline.clear();

View File

@ -276,26 +276,16 @@ class EmotesSettingsController extends State<EmotesSettings> {
}
Future<void> importEmojiZip() async {
final result = await showFutureLoadingDialog<Archive?>(
context: context,
future: () async {
final result = await selectFiles(
context,
type: FileSelectorType.zip,
);
if (result.isEmpty) return null;
final buffer = await result.first.readAsBytes();
final archive = ZipDecoder().decodeBytes(buffer);
return archive;
},
final result = await selectFiles(
context,
type: FileSelectorType.zip,
);
final archive = result.result;
if (archive == null) return;
if (result.isEmpty) return;
final buffer = InputMemoryStream(await result.single.readAsBytes());
final archive = ZipDecoder().decodeStream(buffer);
await showDialog(
context: context,
@ -338,8 +328,6 @@ class EmotesSettingsController extends State<EmotesSettings> {
'${pack.pack.displayName ?? client.userID?.localpart ?? 'emotes'}.zip';
final output = ZipEncoder().encode(archive);
if (output == null) return;
MatrixFile(
name: fileName,
bytes: Uint8List.fromList(output),

View File

@ -23,6 +23,7 @@ import 'dart:io';
import 'dart:isolate';
import 'dart:ui';
import 'package:extera_next/main.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@ -75,6 +76,20 @@ class BackgroundPush {
void _init() async {
try {
mainIsolateReceivePort?.listen(
(message) async {
try {
await notificationTap(
NotificationResponseJson.fromJsonString(message),
client: client,
router: FluffyChatApp.router,
l10n: l10n,
);
} catch (e, s) {
Logs().wtf('Main Notification Tap crashed', e, s);
}
},
);
if (PlatformInfos.isAndroid) {
final port = ReceivePort();
IsolateNameServer.removePortNameMapping('background_tab_port');
@ -103,11 +118,10 @@ class BackgroundPush {
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: (response) => notificationTap(
response,
client: client,
router: FluffyChatApp.router,
l10n: l10n
),
response,
client: client,
router: FluffyChatApp.router,
l10n: l10n),
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
Logs().v('Flutter Local Notifications initialized');
@ -125,7 +139,7 @@ class BackgroundPush {
if (Platform.isAndroid) {
await UnifiedPush.initialize(
onNewEndpoint: _newUpEndpoint,
onRegistrationFailed: _upUnregistered,
onRegistrationFailed: (_, i) => _upUnregistered(i),
onUnregistered: _upUnregistered,
onMessage: _onUpMessage,
);
@ -312,12 +326,8 @@ class BackgroundPush {
final response = details.notificationResponse;
if (response != null) {
notificationTap(
response,
client: client,
router: FluffyChatApp.router,
l10n: l10n
);
notificationTap(response,
client: client, router: FluffyChatApp.router, l10n: l10n);
}
});
}
@ -363,55 +373,18 @@ class BackgroundPush {
);
}
Future<void> goToRoom(NotificationResponse? response) async {
try {
if (response?.payload == null) return;
final arr = response?.payload?.split(' ');
final roomId = arr?[0];
final eventId = arr?[1];
Logs().v('[Push] Attempting to go to room $roomId...');
if (roomId == null || eventId == null) {
return;
}
await client.roomsLoading;
await client.accountDataLoading;
if (client.getRoomById(roomId) == null) {
await client
.waitForRoomInSync(roomId)
.timeout(const Duration(seconds: 30));
}
if (response?.actionId == "read") {
if (AppConfig.sendPublicReadReceipts) {
await client.setReadMarker(roomId, mRead: eventId);
} else {
await client.setReadMarker(roomId, mReadPrivate: eventId);
}
return;
} else if (response?.actionId == "reply") {
final replyText = response?.input;
final room = client.getRoomById(roomId);
if (replyText != null && room != null) {
await room.sendTextEvent(replyText,
inReplyTo: await room.getEventById(eventId));
}
return;
}
FluffyChatApp.router.go(
client.getRoomById(roomId)?.membership == Membership.invite
? '/rooms'
: '/rooms/$roomId',
);
} catch (e, s) {
Logs().e('[Push] Failed to open room', e, s);
}
}
Future<void> setupUp() async {
await UnifiedPushUi(matrix!.context, ["default"], UPFunctions())
.registerAppWithDialog();
await UnifiedPushUi(
context: matrix!.context,
instances: ["default"],
unifiedPushFunctions: UPFunctions(),
showNoDistribDialog: false,
onNoDistribDialogDismissed: () {}, // TODO: Implement me
).registerAppWithDialog();
}
Future<void> _newUpEndpoint(String newEndpoint, String i) async {
Future<void> _newUpEndpoint(PushEndpoint newPushEndpoint, String i) async {
final newEndpoint = newPushEndpoint.url;
upAction = true;
if (newEndpoint.isEmpty) {
await _upUnregistered(i);
@ -471,8 +444,9 @@ class BackgroundPush {
}
}
Future<void> _onUpMessage(Uint8List message, String i) async {
Future<void> _onUpMessage(PushMessage pushMessage, String i) async {
upAction = true;
final message = pushMessage.content;
final data = Map<String, dynamic>.from(
json.decode(utf8.decode(message))['notification'],
);

View File

@ -1,149 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart' hide Key;
import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart';
import 'package:matrix/matrix.dart';
import 'package:path_provider/path_provider.dart';
import 'package:universal_html/html.dart' as html;
// ignore: deprecated_member_use
class FlutterHiveCollectionsDatabase extends HiveCollectionsDatabase {
FlutterHiveCollectionsDatabase(
super.name,
String super.path, {
super.key,
});
static const String _cipherStorageKey = 'hive_encryption_key';
static Future<FlutterHiveCollectionsDatabase> databaseBuilder(
Client client,
) async {
Logs().d('Open Hive...');
HiveAesCipher? hiverCipher;
try {
// Workaround for secure storage is calling Platform.operatingSystem on web
if (kIsWeb) {
// ignore: unawaited_futures
html.window.navigator.storage?.persist();
throw MissingPluginException();
}
const secureStorage = FlutterSecureStorage();
final containsEncryptionKey =
await secureStorage.read(key: _cipherStorageKey) != null;
if (!containsEncryptionKey) {
// do not try to create a buggy secure storage for new Linux users
if (Platform.isLinux) throw MissingPluginException();
final key = Hive.generateSecureKey();
await secureStorage.write(
key: _cipherStorageKey,
value: base64UrlEncode(key),
);
}
// workaround for if we just wrote to the key and it still doesn't exist
final rawEncryptionKey = await secureStorage.read(key: _cipherStorageKey);
if (rawEncryptionKey == null) throw MissingPluginException();
hiverCipher = HiveAesCipher(base64Url.decode(rawEncryptionKey));
} on MissingPluginException catch (_) {
const FlutterSecureStorage()
.delete(key: _cipherStorageKey)
.catchError((_) {});
Logs().i('Hive encryption is not supported on this platform');
} catch (e, s) {
const FlutterSecureStorage()
.delete(key: _cipherStorageKey)
.catchError((_) {});
Logs().w('Unable to init Hive encryption', e, s);
}
final db = FlutterHiveCollectionsDatabase(
'hive_collections_${client.clientName.replaceAll(' ', '_').toLowerCase()}',
await findDatabasePath(client),
key: hiverCipher,
);
try {
await db.open();
} catch (e, s) {
Logs().w('Unable to open Hive. Delete database and storage key...', e, s);
const FlutterSecureStorage().delete(key: _cipherStorageKey);
await db.clear().catchError((_) {});
await Hive.deleteFromDisk();
rethrow;
}
Logs().d('Hive is ready');
return db;
}
static Future<String> findDatabasePath(Client client) async {
var path = client.clientName;
if (!kIsWeb) {
Directory directory;
try {
if (Platform.isLinux) {
directory = await getApplicationSupportDirectory();
} else {
directory = await getApplicationDocumentsDirectory();
}
} catch (_) {
try {
directory = await getLibraryDirectory();
} catch (_) {
directory = Directory.current;
}
}
// do not destroy your stable FluffyChat in debug mode
directory = Directory(
directory.uri.resolve(kDebugMode ? 'hive_debug' : 'hive').toFilePath(),
);
directory.create(recursive: true);
path = directory.path;
}
return path;
}
@override
int get maxFileSize => supportsFileStoring ? 100 * 1000 * 1000 : 0;
@override
bool get supportsFileStoring => !kIsWeb;
Future<String> _getFileStoreDirectory() async {
try {
try {
return (await getTemporaryDirectory()).path;
} catch (_) {
return (await getApplicationDocumentsDirectory()).path;
}
} catch (_) {
return (await getDownloadsDirectory())!.path;
}
}
@override
Future<Uint8List?> getFile(Uri mxcUri) async {
if (!supportsFileStoring) return null;
final tempDirectory = await _getFileStoreDirectory();
final file =
File('$tempDirectory/${Uri.encodeComponent(mxcUri.toString())}');
if (await file.exists() == false) return null;
final bytes = await file.readAsBytes();
return bytes;
}
@override
Future storeFile(Uri mxcUri, Uint8List bytes, int time) async {
if (!supportsFileStoring) return null;
final tempDirectory = await _getFileStoreDirectory();
final file =
File('$tempDirectory/${Uri.encodeComponent(mxcUri.toString())}');
if (await file.exists()) return;
await file.writeAsBytes(bytes);
return;
}
}

View File

@ -110,10 +110,10 @@ Future<MatrixSdkDatabase> _constructDatabase(String clientName) async {
final database = await factory.openDatabase(
path,
options: OpenDatabaseOptions(
version: 1,
// most important : apply encryption when opening the DB
onConfigure: helper?.applyPragmaKey,
singleInstance: false),
version: 1,
// most important : apply encryption when opening the DB
onConfigure: helper?.applyPragmaKey,
),
);
return await MatrixSdkDatabase.init(

View File

@ -7,6 +7,8 @@ class MatrixLocals extends MatrixLocalizations {
MatrixLocals(this.l10n);
@override
String voiceMessage(String senderName, Duration? duration) {
return l10n.voiceMessage;
@ -358,4 +360,17 @@ class MatrixLocals extends MatrixLocalizations {
@override
String get cancelledSend => l10n.sendCanceled;
@override
// TODO: implement pollHasBeenEnded
String get pollHasBeenEnded => throw UnimplementedError();
@override
String startedAPoll(String senderName) {
// TODO: implement startedAPoll
throw UnimplementedError();
}
// This is currently not used, just to keep up with matrix-dart-sdk upstream.
// I will reimplement polls to match fluffychat's, I don't know when...
}

View File

@ -46,11 +46,10 @@ extension NotificationResponseJson on NotificationResponse {
void notificationTapBackground(
NotificationResponse notificationResponse,
) async {
Logs().i('Notification tap in background');
final sendPort = IsolateNameServer.lookupPortByName('background_tab_port');
final sendPort = IsolateNameServer.lookupPortByName(AppConfig.mainIsolatePortName);
if (sendPort != null) {
sendPort.send(notificationResponse.toJsonString());
Logs().i('Notification tap sent to main isolate');
return;
}

View File

@ -1,9 +1,11 @@
import 'dart:async';
import 'package:extera_next/generated/l10n/l10n.dart';
import 'package:matrix/matrix.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:extera_next/generated/l10n/l10n.dart';
import 'package:extera_next/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
import 'package:extera_next/widgets/adaptive_dialogs/show_text_input_dialog.dart';
import 'package:extera_next/widgets/fluffy_chat_app.dart';
@ -34,7 +36,7 @@ extension UiaRequestManager on MatrixState {
minLines: 1,
maxLines: 1,
obscureText: true,
hintText: l10n.password,
hintText: L10n.of(context).password,
));
if (input == null || input.isEmpty) {
return uiaRequest.cancel();
@ -80,24 +82,38 @@ extension UiaRequestManager on MatrixState {
),
);
default:
final url = Uri.parse(
'${client.homeserver}/_matrix/client/r0/auth/$stage/fallback/web?session=${uiaRequest.session}',
final stageUrl = uiaRequest.params
.tryGetMap<String, Object?>(stage)
?.tryGet<String>('url');
final fallbackUrl = client.homeserver!.replace(
path: '/_matrix/client/v3/auth/$stage/fallback/web',
queryParameters: {
'session': uiaRequest.session,
},
);
final url = stageUrl != null
? (Uri.tryParse(stageUrl) ?? fallbackUrl)
: fallbackUrl;
final consent = await showOkCancelAlertDialog(
useRootNavigator: false,
title: l10n.pleaseFollowInstructionsOnWeb,
context: navigatorContext,
okLabel: l10n.open,
cancelLabel: l10n.cancel,
);
if (consent != OkCancelResult.ok) return uiaRequest.cancel();
launchUrl(url, mode: LaunchMode.inAppBrowserView);
final completer = Completer();
final listener =
AppLifecycleListener(onResume: () => completer.complete());
await completer.future;
listener.dispose();
return uiaRequest.completeStage(
AuthenticationData(session: uiaRequest.session),
);
launchUrlString(url.toString());
if (OkCancelResult.ok ==
await showOkCancelAlertDialog(
useRootNavigator: false,
title: l10n.pleaseFollowInstructionsOnWeb,
context: navigatorContext,
okLabel: l10n.next,
cancelLabel: l10n.cancel,
)) {
return uiaRequest.completeStage(
AuthenticationData(session: uiaRequest.session),
);
} else {
return uiaRequest.cancel();
}
}
} catch (e, s) {
Logs().e('Error while background UIA', e, s);
@ -113,4 +129,4 @@ class UiaException implements Exception {
@override
String toString() => reason;
}
}

View File

@ -16,8 +16,11 @@
#include <handy_window/handy_window_plugin.h>
#include <pasteboard/pasteboard_plugin.h>
#include <record_linux/record_linux_plugin.h>
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
#include <sqlcipher_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <webcrypto/webcrypto_plugin.h>
#include <window_manager/window_manager_plugin.h>
#include <window_to_front/window_to_front_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
@ -51,12 +54,21 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) record_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin");
record_linux_plugin_register_with_registrar(record_linux_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
g_autoptr(FlPluginRegistrar) sqlcipher_flutter_libs_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
sqlite3_flutter_libs_plugin_register_with_registrar(sqlcipher_flutter_libs_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
g_autoptr(FlPluginRegistrar) webcrypto_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WebcryptoPlugin");
webcrypto_plugin_register_with_registrar(webcrypto_registrar);
g_autoptr(FlPluginRegistrar) window_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
window_manager_plugin_register_with_registrar(window_manager_registrar);
g_autoptr(FlPluginRegistrar) window_to_front_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowToFrontPlugin");
window_to_front_plugin_register_with_registrar(window_to_front_registrar);

View File

@ -13,8 +13,11 @@ list(APPEND FLUTTER_PLUGIN_LIST
handy_window
pasteboard
record_linux
screen_retriever_linux
sqlcipher_flutter_libs
url_launcher_linux
webcrypto
window_manager
window_to_front
)

View File

@ -24,6 +24,7 @@ import package_info_plus
import pasteboard
import path_provider_foundation
import record_macos
import screen_retriever_macos
import share_plus
import shared_preferences_foundation
import sqflite_darwin
@ -32,6 +33,8 @@ import url_launcher_macos
import video_compress
import video_player_avfoundation
import wakelock_plus
import webcrypto
import window_manager
import window_to_front
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
@ -54,6 +57,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin"))
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
@ -62,5 +66,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
WebcryptoPlugin.register(with: registry.registrar(forPlugin: "WebcryptoPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin"))
}

View File

@ -253,10 +253,10 @@ packages:
dependency: "direct main"
description:
name: cross_file
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
sha256: "942a4791cd385a68ccb3b32c71c427aba508a1bb949b86dff2adbe4049f16239"
url: "https://pub.dev"
source: hosted
version: "0.3.4+2"
version: "0.3.5"
crypto:
dependency: transitive
description:
@ -730,10 +730,10 @@ packages:
dependency: "direct main"
description:
name: flutter_vodozemac
sha256: "54cd3790b6dfdc1afce928f8c46f7eeea9e4f8326f077400894935926f202057"
sha256: "16d4b44dd338689441fe42a80d0184e5c864e9563823de9e7e6371620d2c0590"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
version: "0.4.1"
flutter_web_auth_2:
dependency: "direct main"
description:
@ -1203,10 +1203,10 @@ packages:
description:
path: "."
ref: main
resolved-ref: f678376e3a4825a6e1a00d89585d6bae0843950c
resolved-ref: "8272294736361eae8f3c81d220aaffcf30f38fb1"
url: "https://git.extera.xyz/OfficialDakari/matrix-dart-sdk.git"
source: git
version: "3.0.1"
version: "3.0.2"
meta:
dependency: transitive
description:
@ -1563,10 +1563,10 @@ packages:
dependency: "direct main"
description:
name: qr_code_scanner_plus
sha256: a0f1ac8e13299b3db2646635f252fe2ec67222b848b24ed34d11052faf080bfa
sha256: b764e5004251c58d9dee0c295e6006e05bd8d249e78ac3383abdb5afe0a996cd
url: "https://pub.dev"
source: hosted
version: "2.0.12"
version: "2.0.14"
qr_image:
dependency: "direct main"
description:
@ -1679,6 +1679,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.2"
screen_retriever:
dependency: transitive
description:
name: screen_retriever
sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
screen_retriever_linux:
dependency: transitive
description:
name: screen_retriever_linux
sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18
url: "https://pub.dev"
source: hosted
version: "0.2.0"
screen_retriever_macos:
dependency: transitive
description:
name: screen_retriever_macos
sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
screen_retriever_platform_interface:
dependency: transitive
description:
name: screen_retriever_platform_interface
sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0
url: "https://pub.dev"
source: hosted
version: "0.2.0"
screen_retriever_windows:
dependency: transitive
description:
name: screen_retriever_windows
sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
scroll_to_index:
dependency: "direct main"
description:
@ -2056,34 +2096,50 @@ packages:
dependency: "direct main"
description:
name: unifiedpush
sha256: "6dbed5a6305ca33f1865c7a3d814ae39476b79a2d23ca76a5708f023f405730f"
sha256: "8ed9767f750a1dc6159a77e2171641d0cb825dc87682d1ce1b8618689b79f58e"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
version: "6.2.0"
unifiedpush_android:
dependency: transitive
description:
name: unifiedpush_android
sha256: "7443dece0a850ae956514f809983eb2b39fc518c2c7d24dbfe817198bec89134"
sha256: "556796c81e8151ee8e4275baea2f7191119e8b1412ec35523cc2ac1c44c348bf"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
version: "3.4.0"
unifiedpush_linux:
dependency: transitive
description:
name: unifiedpush_linux
sha256: c062d5eedd1cec70bcd33270cc4e01ae0ff6501f33d471167c06b34a968adfeb
url: "https://pub.dev"
source: hosted
version: "1.0.0"
unifiedpush_platform_interface:
dependency: transitive
description:
name: unifiedpush_platform_interface
sha256: dd588d78a8b2bfc10430e30035526e98caa543d0b7364a6344b5eb4815721c6d
sha256: "83372bc8d794b8b12ef6993b518d7be907dcfc2191bdf6de0ece5c4445d89880"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
version: "4.0.0"
unifiedpush_storage_interface:
dependency: transitive
description:
name: unifiedpush_storage_interface
sha256: b8d423a4695efc616aa21d8ab48fb5ef99d6288c68b56282b8faac1579ceabd9
url: "https://pub.dev"
source: hosted
version: "1.0.0"
unifiedpush_ui:
dependency: "direct main"
description:
name: unifiedpush_ui
sha256: cf86f0214f37debd41f25c0425c8489df85e27f9f8784fed571eb7a86d39ba11
sha256: "1b36b2aa0bc6b61577e2661c1183bd3442969ecf77b4c78174796d324f66dd1d"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
version: "0.2.0"
universal_html:
dependency: "direct main"
description:
@ -2248,10 +2304,10 @@ packages:
dependency: "direct main"
description:
name: vodozemac
sha256: "95cac62ffab94db99e134c8f9aac198f8131a4eed0bed76a6cfc9c72add229b9"
sha256: "39144e20740807731871c9248d811ed5a037b21d0aa9ffcfa630954de74139d9"
url: "https://pub.dev"
source: hosted
version: "0.3.0"
version: "0.4.0"
wakelock_plus:
dependency: "direct main"
description:
@ -2300,6 +2356,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
webcrypto:
dependency: transitive
description:
name: webcrypto
sha256: e393b3d0b01694a8f81efecf278ed7392877130e6e7b29f578863e4f2d0b2ebd
url: "https://pub.dev"
source: hosted
version: "0.5.8"
webdriver:
dependency: transitive
description:
@ -2316,6 +2380,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
webpush_encryption:
dependency: transitive
description:
name: webpush_encryption
sha256: "63046b7d6909f4a72ce3c153fa574726e257aaf21b1995ba063dc241a1b1520b"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
webrtc_interface:
dependency: "direct main"
description:
@ -2340,6 +2412,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.5"
window_manager:
dependency: transitive
description:
name: window_manager
sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
window_to_front:
dependency: transitive
description:

View File

@ -2,7 +2,7 @@ name: extera_next
description: Chat with your friends.
publish_to: none
# On version bump also increase the build number for F-Droid
version: 2.1.0
version: 2.1.1
environment:
sdk: ">=3.0.0 <4.0.0"
@ -16,7 +16,7 @@ dependencies:
blurhash_dart: ^1.2.1
chewie: ^1.11.0
collection: ^1.18.0
cross_file: ^0.3.4+2
cross_file: ^0.3.5
cupertino_icons: any
desktop_drop: ^0.4.4
desktop_notifications: ^0.6.3
@ -47,7 +47,7 @@ dependencies:
git:
url: https://github.com/famedly/flutter_typeahead.git
ref: main
flutter_vodozemac: ^0.3.0
flutter_vodozemac: ^0.4.1
flutter_web_auth_2: ^3.1.1 # Version 4 blocked by https://github.com/MixinNetwork/flutter-plugins/issues/379
flutter_webrtc: ^0.12.9
geolocator: ^13.0.1
@ -79,10 +79,10 @@ dependencies:
pretty_qr_code: ^3.2.1
provider: ^6.0.2
punycode: ^1.0.0
qr_code_scanner_plus: ^2.0.10+1
qr_code_scanner_plus: ^2.0.14
qr_image: ^1.0.0
receive_sharing_intent: ^1.8.1
record: ^6.1.1
record: ^6.1.2
scroll_to_index: ^3.0.1
share_plus: ^10.0.2
shared_preferences: ^2.2.0 # Pinned because https://github.com/flutter/flutter/issues/118401
@ -91,13 +91,13 @@ dependencies:
sqlcipher_flutter_libs: ^0.6.1
swipe_to_action: ^0.3.0
tor_detector_web: ^1.1.0
unifiedpush: ^5.0.1
unifiedpush_ui: ^0.1.0
unifiedpush: ^6.2.0
unifiedpush_ui: ^0.2.0
universal_html: ^2.2.4
url_launcher: ^6.2.5
video_compress: ^3.1.4
video_player: ^2.9.2
vodozemac: ^0.3.0
vodozemac: ^0.4.0
wakelock_plus: ^1.2.2
webrtc_interface: ^1.0.13
dio: ^5.9.0

View File

@ -17,9 +17,12 @@
#include <pasteboard/pasteboard_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <record_windows/record_windows_plugin_c_api.h>
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
#include <share_plus/share_plus_windows_plugin_c_api.h>
#include <sqlcipher_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
#include <webcrypto/webcrypto_plugin.h>
#include <window_manager/window_manager_plugin.h>
#include <window_to_front/window_to_front_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
@ -45,12 +48,18 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
RecordWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("RecordWindowsPluginCApi"));
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
Sqlite3FlutterLibsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WebcryptoPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WebcryptoPlugin"));
WindowManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
WindowToFrontPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowToFrontPlugin"));
}

View File

@ -14,9 +14,12 @@ list(APPEND FLUTTER_PLUGIN_LIST
pasteboard
permission_handler_windows
record_windows
screen_retriever_windows
share_plus
sqlcipher_flutter_libs
url_launcher_windows
webcrypto
window_manager
window_to_front
)