Merge remote-tracking branch 'upstream/main' into yiffed
This commit is contained in:
commit
b515d52e0c
|
@ -118,7 +118,8 @@ class Encryption {
|
||||||
runInRoot(() => keyVerificationManager.handleEventUpdate(update)));
|
runInRoot(() => keyVerificationManager.handleEventUpdate(update)));
|
||||||
}
|
}
|
||||||
if (update.content['sender'] == client.userID &&
|
if (update.content['sender'] == client.userID &&
|
||||||
!update.content['unsigned'].containsKey('transaction_id')) {
|
(!update.content.containsKey('unsigned') ||
|
||||||
|
!update.content['unsigned'].containsKey('transaction_id'))) {
|
||||||
// maybe we need to re-try SSSS secrets
|
// maybe we need to re-try SSSS secrets
|
||||||
unawaited(runInRoot(() => ssss.periodicallyRequestMissingCache()));
|
unawaited(runInRoot(() => ssss.periodicallyRequestMissingCache()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import '../encryption/utils/json_signature_check_extension.dart';
|
||||||
import '../src/utils/logs.dart';
|
import '../src/utils/logs.dart';
|
||||||
import 'encryption.dart';
|
import 'encryption.dart';
|
||||||
import 'utils/olm_session.dart';
|
import 'utils/olm_session.dart';
|
||||||
|
import '../src/utils/run_in_root.dart';
|
||||||
|
|
||||||
class OlmManager {
|
class OlmManager {
|
||||||
final Encryption encryption;
|
final Encryption encryption;
|
||||||
|
@ -344,6 +345,8 @@ class OlmManager {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Map<String, DateTime> _restoredOlmSessionsTime = {};
|
||||||
|
|
||||||
Future<void> restoreOlmSession(String userId, String senderKey) async {
|
Future<void> restoreOlmSession(String userId, String senderKey) async {
|
||||||
if (!client.userDeviceKeys.containsKey(userId)) {
|
if (!client.userDeviceKeys.containsKey(userId)) {
|
||||||
return;
|
return;
|
||||||
|
@ -353,6 +356,15 @@ class OlmManager {
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// per device only one olm session per hour should be restored
|
||||||
|
final mapKey = '$userId;$senderKey';
|
||||||
|
if (_restoredOlmSessionsTime.containsKey(mapKey) &&
|
||||||
|
DateTime.now()
|
||||||
|
.subtract(Duration(hours: 1))
|
||||||
|
.isBefore(_restoredOlmSessionsTime[mapKey])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_restoredOlmSessionsTime[mapKey] = DateTime.now();
|
||||||
await startOutgoingOlmSessions([device]);
|
await startOutgoingOlmSessions([device]);
|
||||||
await client.sendToDeviceEncrypted([device], 'm.dummy', {});
|
await client.sendToDeviceEncrypted([device], 'm.dummy', {});
|
||||||
}
|
}
|
||||||
|
@ -386,7 +398,8 @@ class OlmManager {
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// okay, the thing errored while decrypting. It is safe to assume that the olm session is corrupt and we should generate a new one
|
// okay, the thing errored while decrypting. It is safe to assume that the olm session is corrupt and we should generate a new one
|
||||||
if (client.enableE2eeRecovery) {
|
if (client.enableE2eeRecovery) {
|
||||||
unawaited(restoreOlmSession(event.senderId, senderKey));
|
unawaited(
|
||||||
|
runInRoot(() => restoreOlmSession(event.senderId, senderKey)));
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ class SupportedVersions {
|
||||||
|
|
||||||
SupportedVersions.fromJson(Map<String, dynamic> json) {
|
SupportedVersions.fromJson(Map<String, dynamic> json) {
|
||||||
versions = json['versions'].cast<String>();
|
versions = json['versions'].cast<String>();
|
||||||
unstableFeatures = Map<String, bool>.from(json['unstable_features']);
|
unstableFeatures = Map<String, bool>.from(json['unstable_features'] ?? {});
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
|
|
|
@ -893,6 +893,8 @@ class Client extends MatrixApi {
|
||||||
|
|
||||||
var update = RoomUpdate.fromSyncRoomUpdate(room, id);
|
var update = RoomUpdate.fromSyncRoomUpdate(room, id);
|
||||||
if (database != null) {
|
if (database != null) {
|
||||||
|
// TODO: This method seems to be rather slow for some updates
|
||||||
|
// Perhaps don't dynamically build that one query?
|
||||||
await database.storeRoomUpdate(this.id, update, getRoomById(id));
|
await database.storeRoomUpdate(this.id, update, getRoomById(id));
|
||||||
}
|
}
|
||||||
_updateRoomsByRoomUpdate(update);
|
_updateRoomsByRoomUpdate(update);
|
||||||
|
@ -907,6 +909,7 @@ class Client extends MatrixApi {
|
||||||
/// Handle now all room events and save them in the database
|
/// Handle now all room events and save them in the database
|
||||||
if (room is JoinedRoomUpdate) {
|
if (room is JoinedRoomUpdate) {
|
||||||
if (room.state?.isNotEmpty ?? false) {
|
if (room.state?.isNotEmpty ?? false) {
|
||||||
|
// TODO: This method seems to be comperatively slow for some updates
|
||||||
await _handleRoomEvents(
|
await _handleRoomEvents(
|
||||||
id, room.state.map((i) => i.toJson()).toList(), 'state');
|
id, room.state.map((i) => i.toJson()).toList(), 'state');
|
||||||
handledEvents = true;
|
handledEvents = true;
|
||||||
|
@ -920,6 +923,7 @@ class Client extends MatrixApi {
|
||||||
handledEvents = true;
|
handledEvents = true;
|
||||||
}
|
}
|
||||||
if (room.ephemeral?.isNotEmpty ?? false) {
|
if (room.ephemeral?.isNotEmpty ?? false) {
|
||||||
|
// TODO: This method seems to be comperatively slow for some updates
|
||||||
await _handleEphemerals(
|
await _handleEphemerals(
|
||||||
id, room.ephemeral.map((i) => i.toJson()).toList());
|
id, room.ephemeral.map((i) => i.toJson()).toList());
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,51 @@ class EmoteSyntax extends InlineSyntax {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class InlineLatexSyntax extends InlineSyntax {
|
||||||
|
InlineLatexSyntax() : super(r'(?<=\s|^)\$(?=\S)([^\n$]+)(?<=\S)\$(?=\s|$)');
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool onMatch(InlineParser parser, Match match) {
|
||||||
|
final latex = htmlEscape.convert(match[1]);
|
||||||
|
final element = Element('span', [Element.text('code', latex)]);
|
||||||
|
element.attributes['data-mx-maths'] = latex;
|
||||||
|
parser.addNode(element);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BlockLatexSyntax extends BlockSyntax {
|
||||||
|
@override
|
||||||
|
RegExp get pattern => RegExp(r'^[ ]{0,3}\${2}\s*$');
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> parseChildLines(BlockParser parser) {
|
||||||
|
var childLines = <String>[];
|
||||||
|
parser.advance();
|
||||||
|
while (!parser.isDone) {
|
||||||
|
if (!pattern.hasMatch(parser.current)) {
|
||||||
|
childLines.add(parser.current);
|
||||||
|
parser.advance();
|
||||||
|
} else {
|
||||||
|
parser.advance();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return childLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Node parse(BlockParser parser) {
|
||||||
|
final childLines = parseChildLines(parser);
|
||||||
|
final latex = htmlEscape.convert(childLines.join('\n'));
|
||||||
|
final element = Element('div', [
|
||||||
|
Element('pre', [Element.text('code', latex)])
|
||||||
|
]);
|
||||||
|
element.attributes['data-mx-maths'] = latex;
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PillSyntax extends InlineSyntax {
|
class PillSyntax extends InlineSyntax {
|
||||||
PillSyntax() : super(r'([@#!][^\s:]*:[^\s]+\.\w+)');
|
PillSyntax() : super(r'([@#!][^\s:]*:[^\s]+\.\w+)');
|
||||||
|
|
||||||
|
@ -94,18 +139,22 @@ String markdown(String text, [Map<String, Map<String, String>> emotePacks]) {
|
||||||
var ret = markdownToHtml(
|
var ret = markdownToHtml(
|
||||||
text,
|
text,
|
||||||
extensionSet: ExtensionSet.commonMark,
|
extensionSet: ExtensionSet.commonMark,
|
||||||
|
blockSyntaxes: [
|
||||||
|
BlockLatexSyntax(),
|
||||||
|
],
|
||||||
inlineSyntaxes: [
|
inlineSyntaxes: [
|
||||||
StrikethroughSyntax(),
|
StrikethroughSyntax(),
|
||||||
LinebreakSyntax(),
|
LinebreakSyntax(),
|
||||||
SpoilerSyntax(),
|
SpoilerSyntax(),
|
||||||
EmoteSyntax(emotePacks),
|
EmoteSyntax(emotePacks),
|
||||||
PillSyntax()
|
PillSyntax(),
|
||||||
|
InlineLatexSyntax(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
var stripPTags = '<p>'.allMatches(ret).length <= 1;
|
var stripPTags = '<p>'.allMatches(ret).length <= 1;
|
||||||
if (stripPTags) {
|
if (stripPTags) {
|
||||||
final otherBlockTags = [
|
const otherBlockTags = {
|
||||||
'table',
|
'table',
|
||||||
'pre',
|
'pre',
|
||||||
'ol',
|
'ol',
|
||||||
|
@ -116,8 +165,9 @@ String markdown(String text, [Map<String, Map<String, String>> emotePacks]) {
|
||||||
'h4',
|
'h4',
|
||||||
'h5',
|
'h5',
|
||||||
'h6',
|
'h6',
|
||||||
'blockquote'
|
'blockquote',
|
||||||
];
|
'div',
|
||||||
|
};
|
||||||
for (final tag in otherBlockTags) {
|
for (final tag in otherBlockTags) {
|
||||||
// we check for the close tag as the opening one might have attributes
|
// we check for the close tag as the opening one might have attributes
|
||||||
if (ret.contains('</${tag}>')) {
|
if (ret.contains('</${tag}>')) {
|
||||||
|
|
|
@ -70,5 +70,11 @@ void main() {
|
||||||
expect(markdown('!blah:example.org'),
|
expect(markdown('!blah:example.org'),
|
||||||
'<a href="https://matrix.to/#/!blah:example.org">!blah:example.org</a>');
|
'<a href="https://matrix.to/#/!blah:example.org">!blah:example.org</a>');
|
||||||
});
|
});
|
||||||
|
test('latex', () {
|
||||||
|
expect(markdown('meep \$\\frac{2}{3}\$'),
|
||||||
|
'meep <span data-mx-maths="\\frac{2}{3}"><code>\\frac{2}{3}</code></span>');
|
||||||
|
expect(markdown('hey\n\$\$\nbeep\nboop\n\$\$\nmeow'),
|
||||||
|
'<p>hey</p>\n<div data-mx-maths="beep\nboop">\n<pre><code>beep\nboop</code></pre>\n</div>\n<p>meow</p>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue