feat(service): Implement automatic sticker pack downloading
This commit is contained in:
parent
f04729261b
commit
e373f5cffe
@ -250,6 +250,14 @@ files:
|
|||||||
implements:
|
implements:
|
||||||
- JsonImplementation
|
- JsonImplementation
|
||||||
attributes:
|
attributes:
|
||||||
|
- name: StickerPackAddedEvent
|
||||||
|
extends: BackgroundEvent
|
||||||
|
implements:
|
||||||
|
- JsonImplementation
|
||||||
|
attributes:
|
||||||
|
stickerPack:
|
||||||
|
type: StickerPack
|
||||||
|
deserialise: true
|
||||||
generate_builder: true
|
generate_builder: true
|
||||||
builder_name: "Event"
|
builder_name: "Event"
|
||||||
builder_baseclass: "BackgroundEvent"
|
builder_baseclass: "BackgroundEvent"
|
||||||
|
@ -10,7 +10,9 @@ import 'package:moxxmpp/moxxmpp.dart' as moxxmpp;
|
|||||||
import 'package:moxxyv2/service/database/database.dart';
|
import 'package:moxxyv2/service/database/database.dart';
|
||||||
import 'package:moxxyv2/service/helpers.dart';
|
import 'package:moxxyv2/service/helpers.dart';
|
||||||
import 'package:moxxyv2/service/httpfiletransfer/helpers.dart';
|
import 'package:moxxyv2/service/httpfiletransfer/helpers.dart';
|
||||||
|
import 'package:moxxyv2/service/service.dart';
|
||||||
import 'package:moxxyv2/service/xmpp.dart';
|
import 'package:moxxyv2/service/xmpp.dart';
|
||||||
|
import 'package:moxxyv2/shared/events.dart';
|
||||||
import 'package:moxxyv2/shared/helpers.dart';
|
import 'package:moxxyv2/shared/helpers.dart';
|
||||||
import 'package:moxxyv2/shared/models/sticker.dart';
|
import 'package:moxxyv2/shared/models/sticker.dart';
|
||||||
import 'package:moxxyv2/shared/models/sticker_pack.dart';
|
import 'package:moxxyv2/shared/models/sticker_pack.dart';
|
||||||
@ -106,6 +108,40 @@ class StickersService {
|
|||||||
|
|
||||||
return stickerDirPath;
|
return stickerDirPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> importFromPubSubWithEvent(moxxmpp.JID jid, String stickerPackId) async {
|
||||||
|
final stickerPack = await importFromPubSub(jid, stickerPackId);
|
||||||
|
if (stickerPack == null) return;
|
||||||
|
|
||||||
|
sendEvent(
|
||||||
|
StickerPackAddedEvent(
|
||||||
|
stickerPack: stickerPack,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes the jid of the host [jid] and the id [stickerPackId] of the sticker pack
|
||||||
|
/// and tries to fetch and install it, including publishing on our own PubSub node.
|
||||||
|
///
|
||||||
|
/// On success, returns the installed StickerPack. On failure, returns null.
|
||||||
|
Future<StickerPack?> importFromPubSub(moxxmpp.JID jid, String stickerPackId) async {
|
||||||
|
final result = await GetIt.I.get<moxxmpp.XmppConnection>()
|
||||||
|
.getManagerById<moxxmpp.StickersManager>(moxxmpp.stickersManager)!
|
||||||
|
.fetchStickerPack(jid.toBare(), stickerPackId);
|
||||||
|
|
||||||
|
if (result.isType<moxxmpp.PubSubError>()) {
|
||||||
|
_log.warning('Failed to fetch sticker pack $jid:$stickerPackId');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final stickerPackRaw = StickerPack.fromMoxxmpp(
|
||||||
|
result.get<moxxmpp.StickerPack>(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Install the sticker pack
|
||||||
|
return installFromPubSub(stickerPackRaw);
|
||||||
|
}
|
||||||
|
|
||||||
Future<StickerPack?> installFromPubSub(StickerPack remotePack) async {
|
Future<StickerPack?> installFromPubSub(StickerPack remotePack) async {
|
||||||
assert(!remotePack.local, 'Sticker pack must be remote');
|
assert(!remotePack.local, 'Sticker pack must be remote');
|
||||||
@ -175,33 +211,7 @@ class StickersService {
|
|||||||
|
|
||||||
// Publish but don't block
|
// Publish but don't block
|
||||||
unawaited(
|
unawaited(
|
||||||
_publishStickerPack(
|
_publishStickerPack(remotePack.toMoxxmpp()),
|
||||||
moxxmpp.StickerPack(
|
|
||||||
remotePack.id,
|
|
||||||
remotePack.name,
|
|
||||||
remotePack.description,
|
|
||||||
moxxmpp.hashFunctionFromName(remotePack.hashAlgorithm),
|
|
||||||
remotePack.hashValue,
|
|
||||||
remotePack.stickers
|
|
||||||
.map((sticker) => moxxmpp.Sticker(
|
|
||||||
moxxmpp.FileMetadataData(
|
|
||||||
mediaType: sticker.mediaType,
|
|
||||||
desc: sticker.desc,
|
|
||||||
size: sticker.size,
|
|
||||||
width: sticker.width,
|
|
||||||
height: sticker.height,
|
|
||||||
thumbnails: [],
|
|
||||||
hashes: sticker.hashes,
|
|
||||||
),
|
|
||||||
sticker.urlSources
|
|
||||||
// ignore: unnecessary_lambdas
|
|
||||||
.map((src) => moxxmpp.StatelessFileSharingUrlSource(src))
|
|
||||||
.toList(),
|
|
||||||
sticker.suggests,
|
|
||||||
),).toList(),
|
|
||||||
remotePack.restricted,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return remotePack.copyWith(
|
return remotePack.copyWith(
|
||||||
|
@ -28,6 +28,7 @@ import 'package:moxxyv2/service/preferences.dart';
|
|||||||
import 'package:moxxyv2/service/roster.dart';
|
import 'package:moxxyv2/service/roster.dart';
|
||||||
import 'package:moxxyv2/service/service.dart';
|
import 'package:moxxyv2/service/service.dart';
|
||||||
import 'package:moxxyv2/service/state.dart';
|
import 'package:moxxyv2/service/state.dart';
|
||||||
|
import 'package:moxxyv2/service/stickers.dart';
|
||||||
import 'package:moxxyv2/shared/error_types.dart';
|
import 'package:moxxyv2/shared/error_types.dart';
|
||||||
import 'package:moxxyv2/shared/eventhandler.dart';
|
import 'package:moxxyv2/shared/eventhandler.dart';
|
||||||
import 'package:moxxyv2/shared/events.dart';
|
import 'package:moxxyv2/shared/events.dart';
|
||||||
@ -1170,7 +1171,30 @@ class XmppService {
|
|||||||
final stickerHashKey = event.stickerPackId != null ?
|
final stickerHashKey = event.stickerPackId != null ?
|
||||||
getStickerHashKey(event.sfs!.metadata.hashes) :
|
getStickerHashKey(event.sfs!.metadata.hashes) :
|
||||||
null;
|
null;
|
||||||
|
// The potential sticker pack
|
||||||
|
final stickerPack = event.stickerPackId != null ?
|
||||||
|
await GetIt.I.get<StickersService>().getStickerPackById(
|
||||||
|
event.stickerPackId!,
|
||||||
|
) :
|
||||||
|
null;
|
||||||
|
|
||||||
|
// Automatically download the sticker pack, if
|
||||||
|
// - a sticker was received,
|
||||||
|
// - the sender is in the roster,
|
||||||
|
// - we don't have the sticker pack locally,
|
||||||
|
// - and it is enabled in the settings
|
||||||
|
if (event.stickerPackId != null &&
|
||||||
|
stickerPack == null &&
|
||||||
|
prefs.autoDownloadStickersFromContacts &&
|
||||||
|
isInRoster) {
|
||||||
|
unawaited(
|
||||||
|
GetIt.I.get<StickersService>().importFromPubSubWithEvent(
|
||||||
|
event.fromJid,
|
||||||
|
event.stickerPackId!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the message in the database
|
// Create the message in the database
|
||||||
final ms = GetIt.I.get<MessageService>();
|
final ms = GetIt.I.get<MessageService>();
|
||||||
final dimensions = _getDimensions(event);
|
final dimensions = _getDimensions(event);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:moxxmpp/moxxmpp.dart' as moxxmpp;
|
||||||
|
import 'package:moxxyv2/service/helpers.dart';
|
||||||
|
|
||||||
part 'sticker.freezed.dart';
|
part 'sticker.freezed.dart';
|
||||||
part 'sticker.g.dart';
|
part 'sticker.g.dart';
|
||||||
@ -22,6 +24,24 @@ class Sticker with _$Sticker {
|
|||||||
) = _Sticker;
|
) = _Sticker;
|
||||||
|
|
||||||
const Sticker._();
|
const Sticker._();
|
||||||
|
|
||||||
|
/// Moxxmpp
|
||||||
|
factory Sticker.fromMoxxmpp(moxxmpp.Sticker sticker, String stickerPackId) => Sticker(
|
||||||
|
getStickerHashKey(sticker.metadata.hashes),
|
||||||
|
sticker.metadata.mediaType!,
|
||||||
|
sticker.metadata.desc!,
|
||||||
|
sticker.metadata.size!,
|
||||||
|
sticker.metadata.width,
|
||||||
|
sticker.metadata.height,
|
||||||
|
sticker.metadata.hashes,
|
||||||
|
sticker.sources
|
||||||
|
.whereType<moxxmpp.StatelessFileSharingUrlSource>()
|
||||||
|
.map((src) => src.url)
|
||||||
|
.toList(),
|
||||||
|
'',
|
||||||
|
stickerPackId,
|
||||||
|
sticker.suggests,
|
||||||
|
);
|
||||||
|
|
||||||
/// JSON
|
/// JSON
|
||||||
factory Sticker.fromJson(Map<String, dynamic> json) => _$StickerFromJson(json);
|
factory Sticker.fromJson(Map<String, dynamic> json) => _$StickerFromJson(json);
|
||||||
@ -48,4 +68,21 @@ class Sticker with _$Sticker {
|
|||||||
'suggests': jsonEncode(suggests),
|
'suggests': jsonEncode(suggests),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moxxmpp.Sticker toMoxxmpp() => moxxmpp.Sticker(
|
||||||
|
moxxmpp.FileMetadataData(
|
||||||
|
mediaType: mediaType,
|
||||||
|
desc: desc,
|
||||||
|
size: size,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
thumbnails: [],
|
||||||
|
hashes: hashes,
|
||||||
|
),
|
||||||
|
urlSources
|
||||||
|
// ignore: unnecessary_lambdas
|
||||||
|
.map((src) => moxxmpp.StatelessFileSharingUrlSource(src))
|
||||||
|
.toList(),
|
||||||
|
suggests,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:moxxmpp/moxxmpp.dart' as moxxmpp;
|
||||||
import 'package:moxxyv2/service/database/helpers.dart';
|
import 'package:moxxyv2/service/database/helpers.dart';
|
||||||
import 'package:moxxyv2/shared/models/sticker.dart';
|
import 'package:moxxyv2/shared/models/sticker.dart';
|
||||||
|
|
||||||
@ -19,6 +20,20 @@ class StickerPack with _$StickerPack {
|
|||||||
) = _StickerPack;
|
) = _StickerPack;
|
||||||
|
|
||||||
const StickerPack._();
|
const StickerPack._();
|
||||||
|
|
||||||
|
/// Moxxmpp
|
||||||
|
factory StickerPack.fromMoxxmpp(moxxmpp.StickerPack pack, bool local) => StickerPack(
|
||||||
|
pack.id,
|
||||||
|
pack.name,
|
||||||
|
pack.summary,
|
||||||
|
pack.stickers
|
||||||
|
.map((sticker) => Sticker.fromMoxxmpp(sticker, pack.id))
|
||||||
|
.toList(),
|
||||||
|
pack.hashAlgorithm.toName(),
|
||||||
|
pack.hashValue,
|
||||||
|
pack.restricted,
|
||||||
|
local,
|
||||||
|
);
|
||||||
|
|
||||||
/// JSON
|
/// JSON
|
||||||
factory StickerPack.fromJson(Map<String, dynamic> json) => _$StickerPackFromJson(json);
|
factory StickerPack.fromJson(Map<String, dynamic> json) => _$StickerPackFromJson(json);
|
||||||
@ -43,5 +58,17 @@ class StickerPack with _$StickerPack {
|
|||||||
...json,
|
...json,
|
||||||
'restricted': boolToInt(restricted),
|
'restricted': boolToInt(restricted),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moxxmpp.StickerPack toMoxxmpp() => moxxmpp.StickerPack(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
moxxmpp.hashFunctionFromName(hashAlgorithm),
|
||||||
|
hashValue,
|
||||||
|
stickers
|
||||||
|
.map((sticker) => sticker.toMoxxmpp())
|
||||||
|
.toList(),
|
||||||
|
restricted,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import 'package:moxxyv2/ui/bloc/conversations_bloc.dart' as conversations;
|
|||||||
import 'package:moxxyv2/ui/bloc/newconversation_bloc.dart' as new_conversation;
|
import 'package:moxxyv2/ui/bloc/newconversation_bloc.dart' as new_conversation;
|
||||||
import 'package:moxxyv2/ui/bloc/profile_bloc.dart' as profile;
|
import 'package:moxxyv2/ui/bloc/profile_bloc.dart' as profile;
|
||||||
import 'package:moxxyv2/ui/bloc/sharedmedia_bloc.dart' as sharedmedia;
|
import 'package:moxxyv2/ui/bloc/sharedmedia_bloc.dart' as sharedmedia;
|
||||||
|
import 'package:moxxyv2/ui/bloc/stickers_bloc.dart' as stickers;
|
||||||
import 'package:moxxyv2/ui/prestart.dart';
|
import 'package:moxxyv2/ui/prestart.dart';
|
||||||
import 'package:moxxyv2/ui/service/progress.dart';
|
import 'package:moxxyv2/ui/service/progress.dart';
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ void setupEventHandler() {
|
|||||||
EventTypeMatcher<PreStartDoneEvent>(preStartDone),
|
EventTypeMatcher<PreStartDoneEvent>(preStartDone),
|
||||||
EventTypeMatcher<ServiceReadyEvent>(onServiceReady),
|
EventTypeMatcher<ServiceReadyEvent>(onServiceReady),
|
||||||
EventTypeMatcher<MessageNotificationTappedEvent>(onNotificationTappend),
|
EventTypeMatcher<MessageNotificationTappedEvent>(onNotificationTappend),
|
||||||
|
EventTypeMatcher<StickerPackAddedEvent>(onStickerPackAdded),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
GetIt.I.registerSingleton<EventHandler>(handler);
|
GetIt.I.registerSingleton<EventHandler>(handler);
|
||||||
@ -159,3 +161,9 @@ Future<void> onNotificationTappend(MessageNotificationTappedEvent event, { dynam
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> onStickerPackAdded(StickerPackAddedEvent event, { dynamic extra }) async {
|
||||||
|
GetIt.I.get<stickers.StickersBloc>().add(
|
||||||
|
stickers.StickerPackAddedEvent(event.stickerPack),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user