Merge pull request #2929 from pangeachat/fluffychat-merge
Fluffychat merge
This commit is contained in:
commit
b0471a7447
28 changed files with 418 additions and 481 deletions
|
|
@ -30,7 +30,7 @@
|
|||
- chore: Use Cupertino Activity Indicator in ChatEventList (krille-chan)
|
||||
- chore: Use other join endpoint for room upgrades (Krille)
|
||||
- fix(macos): update dependencies to make the build work (Rafał Hirsch)
|
||||
- fix: Add missing <s> html tag to render (Krille)
|
||||
- fix: Add missing \<s> html tag to render (Krille)
|
||||
- fix: Consistent element padding between server picker and login view (xegim)
|
||||
- fix: Index of numbered lists are off (Krille)
|
||||
- fix: never use a transition on the shell route (Rafał Hirsch)
|
||||
|
|
|
|||
|
|
@ -705,6 +705,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"countInvited": "{count} invited",
|
||||
"@countInvited": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
"count": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"create": "Create",
|
||||
"@create": {
|
||||
"type": "String",
|
||||
|
|
@ -3199,6 +3208,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"sentVoiceMessage": "\uD83C\uDF99\uFE0F {duration} - {sender}",
|
||||
"@sentVoiceMessage": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
"sender": {
|
||||
"type": "String"
|
||||
},
|
||||
"duration": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deletePushRuleCanNotBeUndone": "If you delete this notification setting, this can not be undone.",
|
||||
"more": "More",
|
||||
"shareKeysWith": "Share keys with...",
|
||||
|
|
|
|||
|
|
@ -6083,4 +6083,4 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4382,4 +4382,4 @@
|
|||
"type": "String",
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -327,10 +327,14 @@
|
|||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ abstract class AppConfig {
|
|||
// static String _applicationName = 'FluffyChat';
|
||||
static String _applicationName = 'Pangea Chat';
|
||||
// #Pangea
|
||||
|
||||
static String get applicationName => _applicationName;
|
||||
static String? _applicationWelcomeMessage;
|
||||
|
||||
|
|
@ -16,7 +17,8 @@ abstract class AppConfig {
|
|||
// #Pangea
|
||||
// static String _defaultHomeserver = 'matrix.org';
|
||||
static String get _defaultHomeserver => Environment.synapseURL;
|
||||
// #Pangea
|
||||
// Pangea#
|
||||
|
||||
static String get defaultHomeserver => _defaultHomeserver;
|
||||
static double fontSizeFactor = 1;
|
||||
static const Color chatColor = primaryColor;
|
||||
|
|
@ -24,6 +26,7 @@ abstract class AppConfig {
|
|||
static const double messageFontSize = 16.0;
|
||||
static const bool allowOtherHomeservers = true;
|
||||
static const bool enableRegistration = true;
|
||||
// #Pangea
|
||||
static const double toolbarMaxHeight = 250.0;
|
||||
static const double toolbarMinHeight = 200.0;
|
||||
static const double toolbarMinWidth = 350.0;
|
||||
|
|
@ -82,6 +85,7 @@ abstract class AppConfig {
|
|||
// 'https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md';
|
||||
static String _privacyUrl = "https://www.pangeachat.com/privacy";
|
||||
//Pangea#
|
||||
|
||||
static String get privacyUrl => _privacyUrl;
|
||||
// #Pangea
|
||||
// static const String website = 'https://fluffychat.im';
|
||||
|
|
@ -97,19 +101,21 @@ abstract class AppConfig {
|
|||
// #Pangea
|
||||
// static const String appOpenUrlScheme = 'im.fluffychat';
|
||||
static const String appOpenUrlScheme = 'matrix.pangea.chat';
|
||||
static String _webBaseUrl = 'https://fluffychat.im/web';
|
||||
// Pangea#
|
||||
static String _webBaseUrl = 'https://fluffychat.im/web';
|
||||
|
||||
static String get webBaseUrl => _webBaseUrl;
|
||||
//#Pangea
|
||||
static const String sourceCodeUrl = 'https://gitlab.com/famedly/fluffychat';
|
||||
static const String sourceCodeUrl =
|
||||
'https://github.com/krille-chan/fluffychat';
|
||||
// #Pangea
|
||||
// static const String supportUrl =
|
||||
// 'https://gitlab.com/famedly/fluffychat/issues';
|
||||
// 'https://github.com/krille-chan/fluffychat/issues';
|
||||
// static const String changelogUrl =
|
||||
// 'https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md';
|
||||
static const String supportUrl = 'https://www.pangeachat.com/faqs';
|
||||
static const String termsOfServiceUrl =
|
||||
'https://www.pangeachat.com/terms-of-service';
|
||||
// static const String changelogUrl =
|
||||
// 'https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md';
|
||||
//Pangea#
|
||||
// Pangea#
|
||||
static final Uri newIssueUrl = Uri(
|
||||
scheme: 'https',
|
||||
host: 'github.com',
|
||||
|
|
@ -145,21 +151,9 @@ abstract class AppConfig {
|
|||
static const String schemePrefix = 'matrix:';
|
||||
// #Pangea
|
||||
// static const String pushNotificationsChannelId = 'fluffychat_push';
|
||||
// static const String pushNotificationsChannelName = 'FluffyChat push channel';
|
||||
// static const String pushNotificationsChannelDescription =
|
||||
// 'Push notifications for FluffyChat';
|
||||
// static const String pushNotificationsAppId = 'chat.fluffy.fluffychat';
|
||||
// static const String pushNotificationsGatewayUrl =
|
||||
// 'https://push.fluffychat.im/_matrix/push/v1/notify';
|
||||
// static const String pushNotificationsPusherFormat = 'event_id_only';
|
||||
static const String pushNotificationsChannelId = 'pangeachat_push';
|
||||
static const String pushNotificationsChannelName = 'Pangea Chat push channel';
|
||||
static const String pushNotificationsChannelDescription =
|
||||
'Push notifications for Pangea Chat';
|
||||
static const String pushNotificationsAppId = 'com.talktolearn.chat';
|
||||
static const String pushNotificationsGatewayUrl =
|
||||
'https://sygnal.pangea.chat/_matrix/push/v1/notify';
|
||||
static const String? pushNotificationsPusherFormat = null;
|
||||
// Pangea#
|
||||
static const double borderRadius = 18.0;
|
||||
static const double columnWidth = 360.0;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,10 @@ enum AppSettings<T> {
|
|||
// Pangea#
|
||||
pushNotificationsGatewayUrl<String>(
|
||||
'pushNotificationsGatewayUrl',
|
||||
'https://push.fluffychat.im/_matrix/push/v1/notify',
|
||||
// #Pangea
|
||||
// 'https://push.fluffychat.im/_matrix/push/v1/notify',
|
||||
'https://sygnal.pangea.chat/_matrix/push/v1/notify',
|
||||
// Pangea#
|
||||
),
|
||||
pushNotificationsPusherFormat<String>(
|
||||
'pushNotificationsPusherFormat',
|
||||
|
|
|
|||
|
|
@ -451,8 +451,12 @@ class Message extends StatelessWidget {
|
|||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
if (event.relationshipType ==
|
||||
RelationshipTypes.reply)
|
||||
if ({
|
||||
RelationshipTypes.reply,
|
||||
RelationshipTypes.thread,
|
||||
}.contains(
|
||||
event.relationshipType,
|
||||
))
|
||||
FutureBuilder<Event?>(
|
||||
future: event.getReplyEvent(
|
||||
timeline,
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
|
|||
autoPlay: true,
|
||||
autoInitialize: true,
|
||||
);
|
||||
|
||||
// #Pangea
|
||||
_stopVideoSubscription?.cancel();
|
||||
_stopVideoSubscription =
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'dart:developer';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
|
|
|||
|
|
@ -85,14 +85,12 @@ class ParticipantListItem extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
subtitle:
|
||||
// #Pangea
|
||||
LevelDisplayName(userId: user.id),
|
||||
// Text(
|
||||
// #Pangea
|
||||
subtitle: LevelDisplayName(userId: user.id),
|
||||
// subtitle: Text(
|
||||
// user.id,
|
||||
// maxLines: 1,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// ),
|
||||
// Pangea#
|
||||
leading: Opacity(
|
||||
opacity: user.membership == Membership.join ? 1 : 0.5,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
|
@ -56,28 +57,27 @@ class ClientChooserButton extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
// Currently disabled because of:
|
||||
// https://github.com/matrix-org/matrix-react-sdk/pull/12286
|
||||
/*PopupMenuItem(
|
||||
PopupMenuItem(
|
||||
value: SettingsAction.archive,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.archive_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context)!.archive),
|
||||
],
|
||||
),
|
||||
),*/
|
||||
PopupMenuItem(
|
||||
value: SettingsAction.settings,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.settings_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).settings),
|
||||
Text(L10n.of(context).archive),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!FluffyThemes.isColumnMode(context))
|
||||
PopupMenuItem(
|
||||
value: SettingsAction.settings,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.settings_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).settings),
|
||||
],
|
||||
),
|
||||
),
|
||||
const PopupMenuDivider(),
|
||||
for (final bundle in bundles) ...[
|
||||
if (matrix.accountBundles[bundle]!.length != 1 ||
|
||||
|
|
@ -158,30 +158,22 @@ class ClientChooserButton extends StatelessWidget {
|
|||
matrix.accountBundles.forEach((key, value) => clientCount += value.length);
|
||||
return FutureBuilder<Profile>(
|
||||
future: matrix.client.fetchOwnProfile(),
|
||||
builder: (context, snapshot) => Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
...List.generate(
|
||||
clientCount,
|
||||
(index) => const SizedBox.shrink(),
|
||||
),
|
||||
const SizedBox.shrink(),
|
||||
const SizedBox.shrink(),
|
||||
PopupMenuButton<Object>(
|
||||
onSelected: (o) => _clientSelected(o, context),
|
||||
itemBuilder: _bundleMenuItems,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ??
|
||||
matrix.client.userID!.localpart,
|
||||
size: 32,
|
||||
),
|
||||
builder: (context, snapshot) => Material(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
color: Colors.transparent,
|
||||
child: PopupMenuButton<Object>(
|
||||
onSelected: (o) => _clientSelected(o, context),
|
||||
itemBuilder: _bundleMenuItems,
|
||||
child: Center(
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name:
|
||||
snapshot.data?.displayName ?? matrix.client.userID!.localpart,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,7 @@ class ChatMembersController extends State<ChatMembersPage> {
|
|||
|
||||
final members = this
|
||||
.members
|
||||
?.where(
|
||||
(member) =>
|
||||
membershipFilter == Membership.join ||
|
||||
member.membership == membershipFilter,
|
||||
)
|
||||
?.where((member) => member.membership == membershipFilter)
|
||||
.toList();
|
||||
|
||||
if (filter.isEmpty) {
|
||||
|
|
|
|||
|
|
@ -144,9 +144,30 @@ class ChatMembersView extends StatelessWidget {
|
|||
Membership.ban =>
|
||||
L10n.of(context).banned,
|
||||
Membership.invite =>
|
||||
L10n.of(context).invited,
|
||||
L10n.of(context).countInvited(
|
||||
room.summary
|
||||
.mInvitedMemberCount ??
|
||||
controller.members
|
||||
?.where(
|
||||
(member) =>
|
||||
member.membership ==
|
||||
Membership.invite,
|
||||
)
|
||||
.length ??
|
||||
0,
|
||||
),
|
||||
Membership.join =>
|
||||
L10n.of(context).all,
|
||||
L10n.of(context).countParticipants(
|
||||
room.summary.mJoinedMemberCount ??
|
||||
controller.members
|
||||
?.where(
|
||||
(member) =>
|
||||
member.membership ==
|
||||
Membership.join,
|
||||
)
|
||||
.length ??
|
||||
0,
|
||||
),
|
||||
Membership.knock =>
|
||||
L10n.of(context).knocking,
|
||||
Membership.leave =>
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ class NewPrivateChatView extends StatelessWidget {
|
|||
),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.onSurface,
|
||||
fontSize: 13,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -167,9 +167,15 @@ class NewPrivateChatView extends StatelessWidget {
|
|||
vertical: 24.0,
|
||||
),
|
||||
child: Material(
|
||||
borderRadius:
|
||||
BorderRadius.circular(AppConfig.borderRadius),
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(AppConfig.borderRadius),
|
||||
side: BorderSide(
|
||||
width: 3,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
color: Colors.transparent,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
borderRadius:
|
||||
|
|
@ -179,10 +185,10 @@ class NewPrivateChatView extends StatelessWidget {
|
|||
userId,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32.0),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxWidth: 256),
|
||||
const BoxConstraints(maxWidth: 200),
|
||||
child: PrettyQrView.data(
|
||||
// #Pangea
|
||||
// data: 'https://matrix.to/#/$userId',
|
||||
|
|
@ -191,8 +197,7 @@ class NewPrivateChatView extends StatelessWidget {
|
|||
decoration: PrettyQrDecoration(
|
||||
shape: PrettyQrSmoothSymbol(
|
||||
roundFactor: 1,
|
||||
color:
|
||||
theme.colorScheme.onPrimaryContainer,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class PublicRoomBottomSheetState extends State<PublicRoomBottomSheet> {
|
|||
context: context,
|
||||
future: () async => client.knockRoom(
|
||||
roomAlias ?? chunk!.roomId,
|
||||
serverName: via,
|
||||
via: via,
|
||||
),
|
||||
onSuccess: () => L10n.of(context).knockSpaceSuccess,
|
||||
delay: false,
|
||||
|
|
|
|||
|
|
@ -132,9 +132,6 @@ abstract class ClientManager {
|
|||
},
|
||||
logLevel: kReleaseMode ? Level.warning : Level.verbose,
|
||||
databaseBuilder: flutterMatrixSdkDatabaseBuilder,
|
||||
// #Pangea
|
||||
// legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder,
|
||||
// Pangea#
|
||||
supportedLoginTypes: {
|
||||
AuthenticationTypes.password,
|
||||
AuthenticationTypes.sso,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,6 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
|||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'cipher.dart';
|
||||
|
||||
|
|
@ -74,7 +73,7 @@ Future<DatabaseApi> flutterMatrixSdkDatabaseBuilder(Client client) async {
|
|||
Logs().e('Unable to send error notification', e, s);
|
||||
}
|
||||
|
||||
return FlutterHiveCollectionsDatabase.databaseBuilder(client);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// This is a temporary helper class until there is a proper solution to this with the new system
|
||||
|
|
@ -353,4 +354,21 @@ class MatrixLocals extends MatrixLocalizations {
|
|||
|
||||
@override
|
||||
String get cancelledSend => l10n.sendCanceled;
|
||||
|
||||
@override
|
||||
String voiceMessage(String senderName, Duration? duration) {
|
||||
final dateTime = duration == null
|
||||
? null
|
||||
: DateTime.fromMillisecondsSinceEpoch(
|
||||
duration.inSeconds * 1000,
|
||||
);
|
||||
final formattedDuration = dateTime == null
|
||||
? ''
|
||||
: DateFormat(
|
||||
DateFormat.MINUTE_SECOND,
|
||||
l10n.localeName,
|
||||
).format(dateTime);
|
||||
|
||||
return l10n.sentVoiceMessage(senderName, formattedDuration);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ Future<void> _tryPushHelper(
|
|||
.first;
|
||||
final event = await client.getEventByPushNotification(
|
||||
notification,
|
||||
storeInDatabase: isBackgroundMessage,
|
||||
storeInDatabase: false,
|
||||
);
|
||||
|
||||
if (event == null) {
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ class UrlLauncher {
|
|||
await PublicRoomBottomSheet.show(
|
||||
context: context,
|
||||
roomAlias: identityParts.primaryIdentifier,
|
||||
// Pangea#
|
||||
);
|
||||
// Pangea#
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,50 +71,48 @@ class Avatar extends StatelessWidget {
|
|||
borderRadius: borderRadius,
|
||||
side: border ?? BorderSide.none,
|
||||
),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child:
|
||||
// #Pangea
|
||||
(userId ?? presenceUserId) == BotName.byEnvironment
|
||||
? BotFace(
|
||||
width: size,
|
||||
expression: BotExpression.idle,
|
||||
useRive: useRive,
|
||||
)
|
||||
:
|
||||
clipBehavior: Clip.antiAlias,
|
||||
// #Pangea
|
||||
// child: noPic
|
||||
child: (userId ?? presenceUserId) == BotName.byEnvironment
|
||||
? BotFace(
|
||||
width: size,
|
||||
expression: BotExpression.idle,
|
||||
useRive: useRive,
|
||||
)
|
||||
: noPic
|
||||
// Pangea#
|
||||
|
||||
noPic
|
||||
? Container(
|
||||
decoration:
|
||||
BoxDecoration(color: name?.lightColorAvatar),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
fallbackLetters,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'RobotoMono',
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: (size / 2.5).roundToDouble(),
|
||||
),
|
||||
),
|
||||
)
|
||||
: MxcImage(
|
||||
client: client,
|
||||
key: ValueKey(mxContent.toString()),
|
||||
cacheKey: '${mxContent}_$size',
|
||||
uri: mxContent,
|
||||
fit: BoxFit.cover,
|
||||
width: size,
|
||||
height: size,
|
||||
placeholder: (_) => Center(
|
||||
child: Icon(
|
||||
Icons.person_2,
|
||||
color: theme.colorScheme.tertiary,
|
||||
size: size / 1.5,
|
||||
),
|
||||
),
|
||||
? Container(
|
||||
decoration:
|
||||
BoxDecoration(color: name?.lightColorAvatar),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
fallbackLetters,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'RobotoMono',
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: (size / 2.5).roundToDouble(),
|
||||
),
|
||||
),
|
||||
)
|
||||
: MxcImage(
|
||||
client: client,
|
||||
key: ValueKey(mxContent.toString()),
|
||||
cacheKey: '${mxContent}_$size',
|
||||
uri: mxContent,
|
||||
fit: BoxFit.cover,
|
||||
width: size,
|
||||
height: size,
|
||||
placeholder: (_) => Center(
|
||||
child: Icon(
|
||||
Icons.person_2,
|
||||
color: theme.colorScheme.tertiary,
|
||||
size: size / 1.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// #Pangea
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
import lldb
|
||||
|
||||
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
|
||||
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
|
||||
base = frame.register["x0"].GetValueAsAddress()
|
||||
page_len = frame.register["x1"].GetValueAsUnsigned()
|
||||
|
||||
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
|
||||
# first page to see if handled it correctly. This makes diagnosing
|
||||
# misconfiguration (e.g. missing breakpoint) easier.
|
||||
data = bytearray(page_len)
|
||||
data[0:8] = b'IHELPED!'
|
||||
|
||||
error = lldb.SBError()
|
||||
frame.GetThread().GetProcess().WriteMemory(base, data, error)
|
||||
if not error.Success():
|
||||
print(f'Failed to write into {base}[+{page_len}]', error)
|
||||
return
|
||||
|
||||
def __lldb_init_module(debugger: lldb.SBDebugger, _):
|
||||
target = debugger.GetDummyTarget()
|
||||
# Caveat: must use BreakpointCreateByRegEx here and not
|
||||
# BreakpointCreateByName. For some reasons callback function does not
|
||||
# get carried over from dummy target for the later.
|
||||
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
|
||||
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
|
||||
bp.SetAutoContinue(True)
|
||||
print("-- LLDB integration loaded --")
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
command script import --relative-to-command-file flutter_lldb_helper.py
|
||||
386
pubspec.lock
386
pubspec.lock
File diff suppressed because it is too large
Load diff
|
|
@ -18,7 +18,7 @@ dependencies:
|
|||
async: ^2.11.0
|
||||
badges: ^3.1.2
|
||||
blurhash_dart: ^1.2.1
|
||||
chewie: ^1.8.1
|
||||
chewie: ^1.11.0
|
||||
collection: ^1.18.0
|
||||
cross_file: ^0.3.4+2
|
||||
cupertino_icons: any
|
||||
|
|
@ -56,7 +56,7 @@ dependencies:
|
|||
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
|
||||
go_router: ^14.8.1
|
||||
go_router: ^15.1.2
|
||||
handy_window: ^0.4.0
|
||||
hive: ^2.2.3
|
||||
hive_flutter: ^1.1.0
|
||||
|
|
@ -72,8 +72,8 @@ dependencies:
|
|||
matrix:
|
||||
git:
|
||||
url: https://github.com/pangeachat/matrix-dart-sdk.git # repo
|
||||
ref: disable-space-hierarchy-cache # branch
|
||||
# matrix: ^0.39.1
|
||||
ref: main
|
||||
# matrix: ^0.40.0
|
||||
# Pangea#
|
||||
mime: ^1.0.6
|
||||
native_imaging: ^0.2.0
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import 'package:matrix/encryption/utils/key_verification.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart';
|
||||
|
||||
Future<Client> prepareTestClient({
|
||||
bool loggedIn = false,
|
||||
|
|
@ -22,7 +22,7 @@ Future<Client> prepareTestClient({
|
|||
importantStateEvents: <String>{
|
||||
'im.ponies.room_emotes', // we want emotes to work properly
|
||||
},
|
||||
databaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder,
|
||||
databaseBuilder: flutterMatrixSdkDatabaseBuilder,
|
||||
supportedLoginTypes: {
|
||||
AuthenticationTypes.password,
|
||||
AuthenticationTypes.sso,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue