mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-10-09 02:54:14 +00:00
improve games
This commit is contained in:
parent
57fa71af0c
commit
3e321ed53d
53 changed files with 3500 additions and 596 deletions
|
|
@ -12,11 +12,25 @@ Future<void> refreshCatalog() =>
|
||||||
|
|
||||||
/// What the in-app store offers, newest version of each app only.
|
/// What the in-app store offers, newest version of each app only.
|
||||||
///
|
///
|
||||||
/// `languages` is what the UI prefers, most preferred first. Descriptions are
|
/// `languages` is what the UI prefers, most preferred first. Names and
|
||||||
/// cached in every language the catalog carries and picked here, so which
|
/// descriptions are cached in every language the catalog carries and picked
|
||||||
/// language a user reads is never sent anywhere.
|
/// here, so which language a user reads is never sent anywhere.
|
||||||
Future<List<WebxdcStoreApp>> catalog({required List<String> languages}) =>
|
Future<List<WebxdcStoreApp>> catalog({
|
||||||
RustLib.instance.api.crateBridgeWebxdcCatalog(languages: languages);
|
required String groupId,
|
||||||
|
required List<String> languages,
|
||||||
|
}) => RustLib.instance.api.crateBridgeWebxdcCatalog(
|
||||||
|
groupId: groupId,
|
||||||
|
languages: languages,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// One-time apps already placed into a chat, for the profile shortcut.
|
||||||
|
Future<List<WebxdcOneTimeInstance>> oneTimeInstances({
|
||||||
|
required String groupId,
|
||||||
|
required List<String> languages,
|
||||||
|
}) => RustLib.instance.api.crateBridgeWebxdcOneTimeInstances(
|
||||||
|
groupId: groupId,
|
||||||
|
languages: languages,
|
||||||
|
);
|
||||||
|
|
||||||
/// Places an app into a chat and returns the id of the message that carries it.
|
/// Places an app into a chat and returns the id of the message that carries it.
|
||||||
Future<String> createInstance({
|
Future<String> createInstance({
|
||||||
|
|
@ -32,12 +46,17 @@ Future<String> createInstance({
|
||||||
Future<WebxdcInstanceInfo?> instance({required String instanceId}) =>
|
Future<WebxdcInstanceInfo?> instance({required String instanceId}) =>
|
||||||
RustLib.instance.api.crateBridgeWebxdcInstance(instanceId: instanceId);
|
RustLib.instance.api.crateBridgeWebxdcInstance(instanceId: instanceId);
|
||||||
|
|
||||||
/// Downloads and verifies the bundle if it is not already on disk, and returns
|
/// Opens cached code, adopting an update only if already downloaded.
|
||||||
/// where it landed. Called when the user starts an app, never on message
|
/// Downloads and verifies the pinned bundle only when it is missing. Called when the user starts an app, never on message
|
||||||
/// arrival: a message must not be able to make a device fetch anything.
|
/// arrival: a message must not be able to make a device fetch anything.
|
||||||
Future<String> prepareBundle({required String instanceId}) =>
|
Future<String> prepareBundle({required String instanceId}) =>
|
||||||
RustLib.instance.api.crateBridgeWebxdcPrepareBundle(instanceId: instanceId);
|
RustLib.instance.api.crateBridgeWebxdcPrepareBundle(instanceId: instanceId);
|
||||||
|
|
||||||
|
/// Background update check after a webxdc app closes. Downloads only; the
|
||||||
|
/// running version changes on a later prepare_bundle call, never mid-session.
|
||||||
|
Future<void> cacheUpdate({required String instanceId}) =>
|
||||||
|
RustLib.instance.api.crateBridgeWebxdcCacheUpdate(instanceId: instanceId);
|
||||||
|
|
||||||
/// Answers one request the webview made for a file inside the bundle.
|
/// Answers one request the webview made for a file inside the bundle.
|
||||||
///
|
///
|
||||||
/// The platform shim has already established that the request came from this
|
/// The platform shim has already established that the request came from this
|
||||||
|
|
@ -65,6 +84,7 @@ Future<void> sendUpdate({
|
||||||
String? href,
|
String? href,
|
||||||
String? summary,
|
String? summary,
|
||||||
String? document,
|
String? document,
|
||||||
|
String? notify,
|
||||||
}) => RustLib.instance.api.crateBridgeWebxdcSendUpdate(
|
}) => RustLib.instance.api.crateBridgeWebxdcSendUpdate(
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
|
|
@ -72,6 +92,7 @@ Future<void> sendUpdate({
|
||||||
href: href,
|
href: href,
|
||||||
summary: summary,
|
summary: summary,
|
||||||
document: document,
|
document: document,
|
||||||
|
notify: notify,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// The address the running app sees for a participant. Stable inside one
|
/// The address the running app sees for a participant. Stable inside one
|
||||||
|
|
@ -93,6 +114,10 @@ Future<String?> deleteInstance({required String instanceId}) => RustLib
|
||||||
.api
|
.api
|
||||||
.crateBridgeWebxdcDeleteInstance(instanceId: instanceId);
|
.crateBridgeWebxdcDeleteInstance(instanceId: instanceId);
|
||||||
|
|
||||||
|
/// Current members of the instance's chat; no account identifiers leave Rust.
|
||||||
|
Future<String> members({required String instanceId}) =>
|
||||||
|
RustLib.instance.api.crateBridgeWebxdcMembers(instanceId: instanceId);
|
||||||
|
|
||||||
class WebxdcInstanceInfo {
|
class WebxdcInstanceInfo {
|
||||||
final String instanceId;
|
final String instanceId;
|
||||||
final String groupId;
|
final String groupId;
|
||||||
|
|
@ -140,6 +165,41 @@ class WebxdcInstanceInfo {
|
||||||
document == other.document;
|
document == other.document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WebxdcOneTimeInstance {
|
||||||
|
final String instanceId;
|
||||||
|
final String name;
|
||||||
|
final Uint8List? icon;
|
||||||
|
final String? summary;
|
||||||
|
final String? document;
|
||||||
|
|
||||||
|
const WebxdcOneTimeInstance({
|
||||||
|
required this.instanceId,
|
||||||
|
required this.name,
|
||||||
|
this.icon,
|
||||||
|
this.summary,
|
||||||
|
this.document,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
instanceId.hashCode ^
|
||||||
|
name.hashCode ^
|
||||||
|
icon.hashCode ^
|
||||||
|
summary.hashCode ^
|
||||||
|
document.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is WebxdcOneTimeInstance &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
instanceId == other.instanceId &&
|
||||||
|
name == other.name &&
|
||||||
|
icon == other.icon &&
|
||||||
|
summary == other.summary &&
|
||||||
|
document == other.document;
|
||||||
|
}
|
||||||
|
|
||||||
class WebxdcResponse {
|
class WebxdcResponse {
|
||||||
final int status;
|
final int status;
|
||||||
final String mime;
|
final String mime;
|
||||||
|
|
@ -187,6 +247,11 @@ class WebxdcStoreApp {
|
||||||
final String? sourceCodeUrl;
|
final String? sourceCodeUrl;
|
||||||
final Uint8List? icon;
|
final Uint8List? icon;
|
||||||
final PlatformInt64 bundleBytes;
|
final PlatformInt64 bundleBytes;
|
||||||
|
final bool proOnly;
|
||||||
|
final bool oneTime;
|
||||||
|
|
||||||
|
/// The existing instance in this chat when a one-time app was already placed.
|
||||||
|
final String? instanceId;
|
||||||
|
|
||||||
const WebxdcStoreApp({
|
const WebxdcStoreApp({
|
||||||
required this.appId,
|
required this.appId,
|
||||||
|
|
@ -196,6 +261,9 @@ class WebxdcStoreApp {
|
||||||
this.sourceCodeUrl,
|
this.sourceCodeUrl,
|
||||||
this.icon,
|
this.icon,
|
||||||
required this.bundleBytes,
|
required this.bundleBytes,
|
||||||
|
required this.proOnly,
|
||||||
|
required this.oneTime,
|
||||||
|
this.instanceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -206,7 +274,10 @@ class WebxdcStoreApp {
|
||||||
description.hashCode ^
|
description.hashCode ^
|
||||||
sourceCodeUrl.hashCode ^
|
sourceCodeUrl.hashCode ^
|
||||||
icon.hashCode ^
|
icon.hashCode ^
|
||||||
bundleBytes.hashCode;
|
bundleBytes.hashCode ^
|
||||||
|
proOnly.hashCode ^
|
||||||
|
oneTime.hashCode ^
|
||||||
|
instanceId.hashCode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
|
|
@ -219,7 +290,10 @@ class WebxdcStoreApp {
|
||||||
description == other.description &&
|
description == other.description &&
|
||||||
sourceCodeUrl == other.sourceCodeUrl &&
|
sourceCodeUrl == other.sourceCodeUrl &&
|
||||||
icon == other.icon &&
|
icon == other.icon &&
|
||||||
bundleBytes == other.bundleBytes;
|
bundleBytes == other.bundleBytes &&
|
||||||
|
proOnly == other.proOnly &&
|
||||||
|
oneTime == other.oneTime &&
|
||||||
|
instanceId == other.instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebxdcUpdateEntry {
|
class WebxdcUpdateEntry {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -238,6 +238,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
List<SqlValue> dco_decode_list_sql_value(dynamic raw);
|
List<SqlValue> dco_decode_list_sql_value(dynamic raw);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
List<WebxdcOneTimeInstance> dco_decode_list_webxdc_one_time_instance(
|
||||||
|
dynamic raw,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
List<WebxdcStoreApp> dco_decode_list_webxdc_store_app(dynamic raw);
|
List<WebxdcStoreApp> dco_decode_list_webxdc_store_app(dynamic raw);
|
||||||
|
|
||||||
|
|
@ -393,6 +398,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
WebxdcInstanceInfo dco_decode_webxdc_instance_info(dynamic raw);
|
WebxdcInstanceInfo dco_decode_webxdc_instance_info(dynamic raw);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
WebxdcOneTimeInstance dco_decode_webxdc_one_time_instance(dynamic raw);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
WebxdcResponse dco_decode_webxdc_response(dynamic raw);
|
WebxdcResponse dco_decode_webxdc_response(dynamic raw);
|
||||||
|
|
||||||
|
|
@ -641,6 +649,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
List<SqlValue> sse_decode_list_sql_value(SseDeserializer deserializer);
|
List<SqlValue> sse_decode_list_sql_value(SseDeserializer deserializer);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
List<WebxdcOneTimeInstance> sse_decode_list_webxdc_one_time_instance(
|
||||||
|
SseDeserializer deserializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
List<WebxdcStoreApp> sse_decode_list_webxdc_store_app(
|
List<WebxdcStoreApp> sse_decode_list_webxdc_store_app(
|
||||||
SseDeserializer deserializer,
|
SseDeserializer deserializer,
|
||||||
|
|
@ -820,6 +833,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
SseDeserializer deserializer,
|
SseDeserializer deserializer,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
WebxdcOneTimeInstance sse_decode_webxdc_one_time_instance(
|
||||||
|
SseDeserializer deserializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
WebxdcResponse sse_decode_webxdc_response(SseDeserializer deserializer);
|
WebxdcResponse sse_decode_webxdc_response(SseDeserializer deserializer);
|
||||||
|
|
||||||
|
|
@ -1143,6 +1161,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
void sse_encode_list_sql_value(List<SqlValue> self, SseSerializer serializer);
|
void sse_encode_list_sql_value(List<SqlValue> self, SseSerializer serializer);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
void sse_encode_list_webxdc_one_time_instance(
|
||||||
|
List<WebxdcOneTimeInstance> self,
|
||||||
|
SseSerializer serializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
void sse_encode_list_webxdc_store_app(
|
void sse_encode_list_webxdc_store_app(
|
||||||
List<WebxdcStoreApp> self,
|
List<WebxdcStoreApp> self,
|
||||||
|
|
@ -1362,6 +1386,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
SseSerializer serializer,
|
SseSerializer serializer,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
void sse_encode_webxdc_one_time_instance(
|
||||||
|
WebxdcOneTimeInstance self,
|
||||||
|
SseSerializer serializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
void sse_encode_webxdc_response(
|
void sse_encode_webxdc_response(
|
||||||
WebxdcResponse self,
|
WebxdcResponse self,
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
List<SqlValue> dco_decode_list_sql_value(dynamic raw);
|
List<SqlValue> dco_decode_list_sql_value(dynamic raw);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
List<WebxdcOneTimeInstance> dco_decode_list_webxdc_one_time_instance(
|
||||||
|
dynamic raw,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
List<WebxdcStoreApp> dco_decode_list_webxdc_store_app(dynamic raw);
|
List<WebxdcStoreApp> dco_decode_list_webxdc_store_app(dynamic raw);
|
||||||
|
|
||||||
|
|
@ -395,6 +400,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
WebxdcInstanceInfo dco_decode_webxdc_instance_info(dynamic raw);
|
WebxdcInstanceInfo dco_decode_webxdc_instance_info(dynamic raw);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
WebxdcOneTimeInstance dco_decode_webxdc_one_time_instance(dynamic raw);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
WebxdcResponse dco_decode_webxdc_response(dynamic raw);
|
WebxdcResponse dco_decode_webxdc_response(dynamic raw);
|
||||||
|
|
||||||
|
|
@ -643,6 +651,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
List<SqlValue> sse_decode_list_sql_value(SseDeserializer deserializer);
|
List<SqlValue> sse_decode_list_sql_value(SseDeserializer deserializer);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
List<WebxdcOneTimeInstance> sse_decode_list_webxdc_one_time_instance(
|
||||||
|
SseDeserializer deserializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
List<WebxdcStoreApp> sse_decode_list_webxdc_store_app(
|
List<WebxdcStoreApp> sse_decode_list_webxdc_store_app(
|
||||||
SseDeserializer deserializer,
|
SseDeserializer deserializer,
|
||||||
|
|
@ -822,6 +835,11 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
SseDeserializer deserializer,
|
SseDeserializer deserializer,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
WebxdcOneTimeInstance sse_decode_webxdc_one_time_instance(
|
||||||
|
SseDeserializer deserializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
WebxdcResponse sse_decode_webxdc_response(SseDeserializer deserializer);
|
WebxdcResponse sse_decode_webxdc_response(SseDeserializer deserializer);
|
||||||
|
|
||||||
|
|
@ -1145,6 +1163,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
@protected
|
@protected
|
||||||
void sse_encode_list_sql_value(List<SqlValue> self, SseSerializer serializer);
|
void sse_encode_list_sql_value(List<SqlValue> self, SseSerializer serializer);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
void sse_encode_list_webxdc_one_time_instance(
|
||||||
|
List<WebxdcOneTimeInstance> self,
|
||||||
|
SseSerializer serializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
void sse_encode_list_webxdc_store_app(
|
void sse_encode_list_webxdc_store_app(
|
||||||
List<WebxdcStoreApp> self,
|
List<WebxdcStoreApp> self,
|
||||||
|
|
@ -1364,6 +1388,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||||
SseSerializer serializer,
|
SseSerializer serializer,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@protected
|
||||||
|
void sse_encode_webxdc_one_time_instance(
|
||||||
|
WebxdcOneTimeInstance self,
|
||||||
|
SseSerializer serializer,
|
||||||
|
);
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
void sse_encode_webxdc_response(
|
void sse_encode_webxdc_response(
|
||||||
WebxdcResponse self,
|
WebxdcResponse self,
|
||||||
|
|
|
||||||
|
|
@ -641,8 +641,34 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteMessagesByGroupId(String groupId) {
|
Future<void> deleteMessagesByGroupId(String groupId) async {
|
||||||
return (delete(messages)..where((t) => t.groupId.equals(groupId))).go();
|
await transaction(() async {
|
||||||
|
// A one-time app is the chat's durable shared object. Keep its card (and
|
||||||
|
// therefore its instance and update log) while removing the visible chat
|
||||||
|
// history and every ordinary app.
|
||||||
|
await customStatement(
|
||||||
|
'''
|
||||||
|
DELETE FROM messages
|
||||||
|
WHERE group_id = ?
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM webxdc_instances AS instance
|
||||||
|
LEFT JOIN webxdc_apps AS app
|
||||||
|
ON app.app_id = instance.app_id
|
||||||
|
AND app.version = instance.version
|
||||||
|
WHERE instance.instance_id = messages.message_id
|
||||||
|
AND (app.one_time = 1 OR app.app_id IS NULL)
|
||||||
|
)''',
|
||||||
|
[groupId],
|
||||||
|
);
|
||||||
|
await customStatement(
|
||||||
|
'''
|
||||||
|
UPDATE groups
|
||||||
|
SET deleted_content = 1, archived = 0, pinned = 0, draft_message = NULL
|
||||||
|
WHERE group_id = ?''',
|
||||||
|
[groupId],
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleOrNullSelectable<Message> getMessageById(String messageId) {
|
SingleOrNullSelectable<Message> getMessageById(String messageId) {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ class WebxdcApps extends Table {
|
||||||
IntColumn get bundleBytes => integer()();
|
IntColumn get bundleBytes => integer()();
|
||||||
BoolColumn get published => boolean().withDefault(const Constant(true))();
|
BoolColumn get published => boolean().withDefault(const Constant(true))();
|
||||||
IntColumn get cachedAt => integer()();
|
IntColumn get cachedAt => integer()();
|
||||||
|
BoolColumn get proOnly => boolean().withDefault(const Constant(false))();
|
||||||
|
IntColumn get sortOrder => integer().withDefault(const Constant(0))();
|
||||||
|
BoolColumn get oneTime => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {appId, version};
|
Set<Column> get primaryKey => {appId, version};
|
||||||
|
|
|
||||||
|
|
@ -12663,6 +12663,48 @@ class $WebxdcAppsTable extends WebxdcApps
|
||||||
type: DriftSqlType.int,
|
type: DriftSqlType.int,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
|
static const VerificationMeta _proOnlyMeta = const VerificationMeta(
|
||||||
|
'proOnly',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<bool> proOnly = GeneratedColumn<bool>(
|
||||||
|
'pro_only',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
|
'CHECK ("pro_only" IN (0, 1))',
|
||||||
|
),
|
||||||
|
defaultValue: const Constant(false),
|
||||||
|
);
|
||||||
|
static const VerificationMeta _sortOrderMeta = const VerificationMeta(
|
||||||
|
'sortOrder',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<int> sortOrder = GeneratedColumn<int>(
|
||||||
|
'sort_order',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const Constant(0),
|
||||||
|
);
|
||||||
|
static const VerificationMeta _oneTimeMeta = const VerificationMeta(
|
||||||
|
'oneTime',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<bool> oneTime = GeneratedColumn<bool>(
|
||||||
|
'one_time',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
|
'CHECK ("one_time" IN (0, 1))',
|
||||||
|
),
|
||||||
|
defaultValue: const Constant(false),
|
||||||
|
);
|
||||||
@override
|
@override
|
||||||
List<GeneratedColumn> get $columns => [
|
List<GeneratedColumn> get $columns => [
|
||||||
appId,
|
appId,
|
||||||
|
|
@ -12676,6 +12718,9 @@ class $WebxdcAppsTable extends WebxdcApps
|
||||||
bundleBytes,
|
bundleBytes,
|
||||||
published,
|
published,
|
||||||
cachedAt,
|
cachedAt,
|
||||||
|
proOnly,
|
||||||
|
sortOrder,
|
||||||
|
oneTime,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
|
|
@ -12782,6 +12827,24 @@ class $WebxdcAppsTable extends WebxdcApps
|
||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_cachedAtMeta);
|
context.missing(_cachedAtMeta);
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('pro_only')) {
|
||||||
|
context.handle(
|
||||||
|
_proOnlyMeta,
|
||||||
|
proOnly.isAcceptableOrUnknown(data['pro_only']!, _proOnlyMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('sort_order')) {
|
||||||
|
context.handle(
|
||||||
|
_sortOrderMeta,
|
||||||
|
sortOrder.isAcceptableOrUnknown(data['sort_order']!, _sortOrderMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('one_time')) {
|
||||||
|
context.handle(
|
||||||
|
_oneTimeMeta,
|
||||||
|
oneTime.isAcceptableOrUnknown(data['one_time']!, _oneTimeMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12835,6 +12898,18 @@ class $WebxdcAppsTable extends WebxdcApps
|
||||||
DriftSqlType.int,
|
DriftSqlType.int,
|
||||||
data['${effectivePrefix}cached_at'],
|
data['${effectivePrefix}cached_at'],
|
||||||
)!,
|
)!,
|
||||||
|
proOnly: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.bool,
|
||||||
|
data['${effectivePrefix}pro_only'],
|
||||||
|
)!,
|
||||||
|
sortOrder: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}sort_order'],
|
||||||
|
)!,
|
||||||
|
oneTime: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.bool,
|
||||||
|
data['${effectivePrefix}one_time'],
|
||||||
|
)!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12866,6 +12941,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
final int bundleBytes;
|
final int bundleBytes;
|
||||||
final bool published;
|
final bool published;
|
||||||
final int cachedAt;
|
final int cachedAt;
|
||||||
|
final bool proOnly;
|
||||||
|
final int sortOrder;
|
||||||
|
final bool oneTime;
|
||||||
const WebxdcApp({
|
const WebxdcApp({
|
||||||
required this.appId,
|
required this.appId,
|
||||||
required this.version,
|
required this.version,
|
||||||
|
|
@ -12878,6 +12956,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
required this.bundleBytes,
|
required this.bundleBytes,
|
||||||
required this.published,
|
required this.published,
|
||||||
required this.cachedAt,
|
required this.cachedAt,
|
||||||
|
required this.proOnly,
|
||||||
|
required this.sortOrder,
|
||||||
|
required this.oneTime,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
|
|
@ -12897,6 +12978,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
map['bundle_bytes'] = Variable<int>(bundleBytes);
|
map['bundle_bytes'] = Variable<int>(bundleBytes);
|
||||||
map['published'] = Variable<bool>(published);
|
map['published'] = Variable<bool>(published);
|
||||||
map['cached_at'] = Variable<int>(cachedAt);
|
map['cached_at'] = Variable<int>(cachedAt);
|
||||||
|
map['pro_only'] = Variable<bool>(proOnly);
|
||||||
|
map['sort_order'] = Variable<int>(sortOrder);
|
||||||
|
map['one_time'] = Variable<bool>(oneTime);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12915,6 +12999,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
bundleBytes: Value(bundleBytes),
|
bundleBytes: Value(bundleBytes),
|
||||||
published: Value(published),
|
published: Value(published),
|
||||||
cachedAt: Value(cachedAt),
|
cachedAt: Value(cachedAt),
|
||||||
|
proOnly: Value(proOnly),
|
||||||
|
sortOrder: Value(sortOrder),
|
||||||
|
oneTime: Value(oneTime),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12935,6 +13022,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
bundleBytes: serializer.fromJson<int>(json['bundleBytes']),
|
bundleBytes: serializer.fromJson<int>(json['bundleBytes']),
|
||||||
published: serializer.fromJson<bool>(json['published']),
|
published: serializer.fromJson<bool>(json['published']),
|
||||||
cachedAt: serializer.fromJson<int>(json['cachedAt']),
|
cachedAt: serializer.fromJson<int>(json['cachedAt']),
|
||||||
|
proOnly: serializer.fromJson<bool>(json['proOnly']),
|
||||||
|
sortOrder: serializer.fromJson<int>(json['sortOrder']),
|
||||||
|
oneTime: serializer.fromJson<bool>(json['oneTime']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override
|
@override
|
||||||
|
|
@ -12952,6 +13042,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
'bundleBytes': serializer.toJson<int>(bundleBytes),
|
'bundleBytes': serializer.toJson<int>(bundleBytes),
|
||||||
'published': serializer.toJson<bool>(published),
|
'published': serializer.toJson<bool>(published),
|
||||||
'cachedAt': serializer.toJson<int>(cachedAt),
|
'cachedAt': serializer.toJson<int>(cachedAt),
|
||||||
|
'proOnly': serializer.toJson<bool>(proOnly),
|
||||||
|
'sortOrder': serializer.toJson<int>(sortOrder),
|
||||||
|
'oneTime': serializer.toJson<bool>(oneTime),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -12967,6 +13060,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
int? bundleBytes,
|
int? bundleBytes,
|
||||||
bool? published,
|
bool? published,
|
||||||
int? cachedAt,
|
int? cachedAt,
|
||||||
|
bool? proOnly,
|
||||||
|
int? sortOrder,
|
||||||
|
bool? oneTime,
|
||||||
}) => WebxdcApp(
|
}) => WebxdcApp(
|
||||||
appId: appId ?? this.appId,
|
appId: appId ?? this.appId,
|
||||||
version: version ?? this.version,
|
version: version ?? this.version,
|
||||||
|
|
@ -12981,6 +13077,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
bundleBytes: bundleBytes ?? this.bundleBytes,
|
bundleBytes: bundleBytes ?? this.bundleBytes,
|
||||||
published: published ?? this.published,
|
published: published ?? this.published,
|
||||||
cachedAt: cachedAt ?? this.cachedAt,
|
cachedAt: cachedAt ?? this.cachedAt,
|
||||||
|
proOnly: proOnly ?? this.proOnly,
|
||||||
|
sortOrder: sortOrder ?? this.sortOrder,
|
||||||
|
oneTime: oneTime ?? this.oneTime,
|
||||||
);
|
);
|
||||||
WebxdcApp copyWithCompanion(WebxdcAppsCompanion data) {
|
WebxdcApp copyWithCompanion(WebxdcAppsCompanion data) {
|
||||||
return WebxdcApp(
|
return WebxdcApp(
|
||||||
|
|
@ -13005,6 +13104,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
: this.bundleBytes,
|
: this.bundleBytes,
|
||||||
published: data.published.present ? data.published.value : this.published,
|
published: data.published.present ? data.published.value : this.published,
|
||||||
cachedAt: data.cachedAt.present ? data.cachedAt.value : this.cachedAt,
|
cachedAt: data.cachedAt.present ? data.cachedAt.value : this.cachedAt,
|
||||||
|
proOnly: data.proOnly.present ? data.proOnly.value : this.proOnly,
|
||||||
|
sortOrder: data.sortOrder.present ? data.sortOrder.value : this.sortOrder,
|
||||||
|
oneTime: data.oneTime.present ? data.oneTime.value : this.oneTime,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -13021,7 +13123,10 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
..write('bundleSha256: $bundleSha256, ')
|
..write('bundleSha256: $bundleSha256, ')
|
||||||
..write('bundleBytes: $bundleBytes, ')
|
..write('bundleBytes: $bundleBytes, ')
|
||||||
..write('published: $published, ')
|
..write('published: $published, ')
|
||||||
..write('cachedAt: $cachedAt')
|
..write('cachedAt: $cachedAt, ')
|
||||||
|
..write('proOnly: $proOnly, ')
|
||||||
|
..write('sortOrder: $sortOrder, ')
|
||||||
|
..write('oneTime: $oneTime')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
@ -13039,6 +13144,9 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
bundleBytes,
|
bundleBytes,
|
||||||
published,
|
published,
|
||||||
cachedAt,
|
cachedAt,
|
||||||
|
proOnly,
|
||||||
|
sortOrder,
|
||||||
|
oneTime,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
|
|
@ -13054,7 +13162,10 @@ class WebxdcApp extends DataClass implements Insertable<WebxdcApp> {
|
||||||
other.bundleSha256 == this.bundleSha256 &&
|
other.bundleSha256 == this.bundleSha256 &&
|
||||||
other.bundleBytes == this.bundleBytes &&
|
other.bundleBytes == this.bundleBytes &&
|
||||||
other.published == this.published &&
|
other.published == this.published &&
|
||||||
other.cachedAt == this.cachedAt);
|
other.cachedAt == this.cachedAt &&
|
||||||
|
other.proOnly == this.proOnly &&
|
||||||
|
other.sortOrder == this.sortOrder &&
|
||||||
|
other.oneTime == this.oneTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
|
|
@ -13069,6 +13180,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
final Value<int> bundleBytes;
|
final Value<int> bundleBytes;
|
||||||
final Value<bool> published;
|
final Value<bool> published;
|
||||||
final Value<int> cachedAt;
|
final Value<int> cachedAt;
|
||||||
|
final Value<bool> proOnly;
|
||||||
|
final Value<int> sortOrder;
|
||||||
|
final Value<bool> oneTime;
|
||||||
final Value<int> rowid;
|
final Value<int> rowid;
|
||||||
const WebxdcAppsCompanion({
|
const WebxdcAppsCompanion({
|
||||||
this.appId = const Value.absent(),
|
this.appId = const Value.absent(),
|
||||||
|
|
@ -13082,6 +13196,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
this.bundleBytes = const Value.absent(),
|
this.bundleBytes = const Value.absent(),
|
||||||
this.published = const Value.absent(),
|
this.published = const Value.absent(),
|
||||||
this.cachedAt = const Value.absent(),
|
this.cachedAt = const Value.absent(),
|
||||||
|
this.proOnly = const Value.absent(),
|
||||||
|
this.sortOrder = const Value.absent(),
|
||||||
|
this.oneTime = const Value.absent(),
|
||||||
this.rowid = const Value.absent(),
|
this.rowid = const Value.absent(),
|
||||||
});
|
});
|
||||||
WebxdcAppsCompanion.insert({
|
WebxdcAppsCompanion.insert({
|
||||||
|
|
@ -13096,6 +13213,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
required int bundleBytes,
|
required int bundleBytes,
|
||||||
this.published = const Value.absent(),
|
this.published = const Value.absent(),
|
||||||
required int cachedAt,
|
required int cachedAt,
|
||||||
|
this.proOnly = const Value.absent(),
|
||||||
|
this.sortOrder = const Value.absent(),
|
||||||
|
this.oneTime = const Value.absent(),
|
||||||
this.rowid = const Value.absent(),
|
this.rowid = const Value.absent(),
|
||||||
}) : appId = Value(appId),
|
}) : appId = Value(appId),
|
||||||
version = Value(version),
|
version = Value(version),
|
||||||
|
|
@ -13115,6 +13235,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
Expression<int>? bundleBytes,
|
Expression<int>? bundleBytes,
|
||||||
Expression<bool>? published,
|
Expression<bool>? published,
|
||||||
Expression<int>? cachedAt,
|
Expression<int>? cachedAt,
|
||||||
|
Expression<bool>? proOnly,
|
||||||
|
Expression<int>? sortOrder,
|
||||||
|
Expression<bool>? oneTime,
|
||||||
Expression<int>? rowid,
|
Expression<int>? rowid,
|
||||||
}) {
|
}) {
|
||||||
return RawValuesInsertable({
|
return RawValuesInsertable({
|
||||||
|
|
@ -13129,6 +13252,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
if (bundleBytes != null) 'bundle_bytes': bundleBytes,
|
if (bundleBytes != null) 'bundle_bytes': bundleBytes,
|
||||||
if (published != null) 'published': published,
|
if (published != null) 'published': published,
|
||||||
if (cachedAt != null) 'cached_at': cachedAt,
|
if (cachedAt != null) 'cached_at': cachedAt,
|
||||||
|
if (proOnly != null) 'pro_only': proOnly,
|
||||||
|
if (sortOrder != null) 'sort_order': sortOrder,
|
||||||
|
if (oneTime != null) 'one_time': oneTime,
|
||||||
if (rowid != null) 'rowid': rowid,
|
if (rowid != null) 'rowid': rowid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -13145,6 +13271,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
Value<int>? bundleBytes,
|
Value<int>? bundleBytes,
|
||||||
Value<bool>? published,
|
Value<bool>? published,
|
||||||
Value<int>? cachedAt,
|
Value<int>? cachedAt,
|
||||||
|
Value<bool>? proOnly,
|
||||||
|
Value<int>? sortOrder,
|
||||||
|
Value<bool>? oneTime,
|
||||||
Value<int>? rowid,
|
Value<int>? rowid,
|
||||||
}) {
|
}) {
|
||||||
return WebxdcAppsCompanion(
|
return WebxdcAppsCompanion(
|
||||||
|
|
@ -13159,6 +13288,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
bundleBytes: bundleBytes ?? this.bundleBytes,
|
bundleBytes: bundleBytes ?? this.bundleBytes,
|
||||||
published: published ?? this.published,
|
published: published ?? this.published,
|
||||||
cachedAt: cachedAt ?? this.cachedAt,
|
cachedAt: cachedAt ?? this.cachedAt,
|
||||||
|
proOnly: proOnly ?? this.proOnly,
|
||||||
|
sortOrder: sortOrder ?? this.sortOrder,
|
||||||
|
oneTime: oneTime ?? this.oneTime,
|
||||||
rowid: rowid ?? this.rowid,
|
rowid: rowid ?? this.rowid,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -13199,6 +13331,15 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
if (cachedAt.present) {
|
if (cachedAt.present) {
|
||||||
map['cached_at'] = Variable<int>(cachedAt.value);
|
map['cached_at'] = Variable<int>(cachedAt.value);
|
||||||
}
|
}
|
||||||
|
if (proOnly.present) {
|
||||||
|
map['pro_only'] = Variable<bool>(proOnly.value);
|
||||||
|
}
|
||||||
|
if (sortOrder.present) {
|
||||||
|
map['sort_order'] = Variable<int>(sortOrder.value);
|
||||||
|
}
|
||||||
|
if (oneTime.present) {
|
||||||
|
map['one_time'] = Variable<bool>(oneTime.value);
|
||||||
|
}
|
||||||
if (rowid.present) {
|
if (rowid.present) {
|
||||||
map['rowid'] = Variable<int>(rowid.value);
|
map['rowid'] = Variable<int>(rowid.value);
|
||||||
}
|
}
|
||||||
|
|
@ -13219,6 +13360,9 @@ class WebxdcAppsCompanion extends UpdateCompanion<WebxdcApp> {
|
||||||
..write('bundleBytes: $bundleBytes, ')
|
..write('bundleBytes: $bundleBytes, ')
|
||||||
..write('published: $published, ')
|
..write('published: $published, ')
|
||||||
..write('cachedAt: $cachedAt, ')
|
..write('cachedAt: $cachedAt, ')
|
||||||
|
..write('proOnly: $proOnly, ')
|
||||||
|
..write('sortOrder: $sortOrder, ')
|
||||||
|
..write('oneTime: $oneTime, ')
|
||||||
..write('rowid: $rowid')
|
..write('rowid: $rowid')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
|
|
@ -25803,6 +25947,9 @@ typedef $$WebxdcAppsTableCreateCompanionBuilder =
|
||||||
required int bundleBytes,
|
required int bundleBytes,
|
||||||
Value<bool> published,
|
Value<bool> published,
|
||||||
required int cachedAt,
|
required int cachedAt,
|
||||||
|
Value<bool> proOnly,
|
||||||
|
Value<int> sortOrder,
|
||||||
|
Value<bool> oneTime,
|
||||||
Value<int> rowid,
|
Value<int> rowid,
|
||||||
});
|
});
|
||||||
typedef $$WebxdcAppsTableUpdateCompanionBuilder =
|
typedef $$WebxdcAppsTableUpdateCompanionBuilder =
|
||||||
|
|
@ -25818,6 +25965,9 @@ typedef $$WebxdcAppsTableUpdateCompanionBuilder =
|
||||||
Value<int> bundleBytes,
|
Value<int> bundleBytes,
|
||||||
Value<bool> published,
|
Value<bool> published,
|
||||||
Value<int> cachedAt,
|
Value<int> cachedAt,
|
||||||
|
Value<bool> proOnly,
|
||||||
|
Value<int> sortOrder,
|
||||||
|
Value<bool> oneTime,
|
||||||
Value<int> rowid,
|
Value<int> rowid,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -25884,6 +26034,21 @@ class $$WebxdcAppsTableFilterComposer
|
||||||
column: $table.cachedAt,
|
column: $table.cachedAt,
|
||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ColumnFilters<bool> get proOnly => $composableBuilder(
|
||||||
|
column: $table.proOnly,
|
||||||
|
builder: (column) => ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
ColumnFilters<int> get sortOrder => $composableBuilder(
|
||||||
|
column: $table.sortOrder,
|
||||||
|
builder: (column) => ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
ColumnFilters<bool> get oneTime => $composableBuilder(
|
||||||
|
column: $table.oneTime,
|
||||||
|
builder: (column) => ColumnFilters(column),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$WebxdcAppsTableOrderingComposer
|
class $$WebxdcAppsTableOrderingComposer
|
||||||
|
|
@ -25949,6 +26114,21 @@ class $$WebxdcAppsTableOrderingComposer
|
||||||
column: $table.cachedAt,
|
column: $table.cachedAt,
|
||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ColumnOrderings<bool> get proOnly => $composableBuilder(
|
||||||
|
column: $table.proOnly,
|
||||||
|
builder: (column) => ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
ColumnOrderings<int> get sortOrder => $composableBuilder(
|
||||||
|
column: $table.sortOrder,
|
||||||
|
builder: (column) => ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
ColumnOrderings<bool> get oneTime => $composableBuilder(
|
||||||
|
column: $table.oneTime,
|
||||||
|
builder: (column) => ColumnOrderings(column),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$WebxdcAppsTableAnnotationComposer
|
class $$WebxdcAppsTableAnnotationComposer
|
||||||
|
|
@ -26002,6 +26182,15 @@ class $$WebxdcAppsTableAnnotationComposer
|
||||||
|
|
||||||
GeneratedColumn<int> get cachedAt =>
|
GeneratedColumn<int> get cachedAt =>
|
||||||
$composableBuilder(column: $table.cachedAt, builder: (column) => column);
|
$composableBuilder(column: $table.cachedAt, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<bool> get proOnly =>
|
||||||
|
$composableBuilder(column: $table.proOnly, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<int> get sortOrder =>
|
||||||
|
$composableBuilder(column: $table.sortOrder, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<bool> get oneTime =>
|
||||||
|
$composableBuilder(column: $table.oneTime, builder: (column) => column);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$WebxdcAppsTableTableManager
|
class $$WebxdcAppsTableTableManager
|
||||||
|
|
@ -26043,6 +26232,9 @@ class $$WebxdcAppsTableTableManager
|
||||||
Value<int> bundleBytes = const Value.absent(),
|
Value<int> bundleBytes = const Value.absent(),
|
||||||
Value<bool> published = const Value.absent(),
|
Value<bool> published = const Value.absent(),
|
||||||
Value<int> cachedAt = const Value.absent(),
|
Value<int> cachedAt = const Value.absent(),
|
||||||
|
Value<bool> proOnly = const Value.absent(),
|
||||||
|
Value<int> sortOrder = const Value.absent(),
|
||||||
|
Value<bool> oneTime = const Value.absent(),
|
||||||
Value<int> rowid = const Value.absent(),
|
Value<int> rowid = const Value.absent(),
|
||||||
}) => WebxdcAppsCompanion(
|
}) => WebxdcAppsCompanion(
|
||||||
appId: appId,
|
appId: appId,
|
||||||
|
|
@ -26056,6 +26248,9 @@ class $$WebxdcAppsTableTableManager
|
||||||
bundleBytes: bundleBytes,
|
bundleBytes: bundleBytes,
|
||||||
published: published,
|
published: published,
|
||||||
cachedAt: cachedAt,
|
cachedAt: cachedAt,
|
||||||
|
proOnly: proOnly,
|
||||||
|
sortOrder: sortOrder,
|
||||||
|
oneTime: oneTime,
|
||||||
rowid: rowid,
|
rowid: rowid,
|
||||||
),
|
),
|
||||||
createCompanionCallback:
|
createCompanionCallback:
|
||||||
|
|
@ -26071,6 +26266,9 @@ class $$WebxdcAppsTableTableManager
|
||||||
required int bundleBytes,
|
required int bundleBytes,
|
||||||
Value<bool> published = const Value.absent(),
|
Value<bool> published = const Value.absent(),
|
||||||
required int cachedAt,
|
required int cachedAt,
|
||||||
|
Value<bool> proOnly = const Value.absent(),
|
||||||
|
Value<int> sortOrder = const Value.absent(),
|
||||||
|
Value<bool> oneTime = const Value.absent(),
|
||||||
Value<int> rowid = const Value.absent(),
|
Value<int> rowid = const Value.absent(),
|
||||||
}) => WebxdcAppsCompanion.insert(
|
}) => WebxdcAppsCompanion.insert(
|
||||||
appId: appId,
|
appId: appId,
|
||||||
|
|
@ -26084,6 +26282,9 @@ class $$WebxdcAppsTableTableManager
|
||||||
bundleBytes: bundleBytes,
|
bundleBytes: bundleBytes,
|
||||||
published: published,
|
published: published,
|
||||||
cachedAt: cachedAt,
|
cachedAt: cachedAt,
|
||||||
|
proOnly: proOnly,
|
||||||
|
sortOrder: sortOrder,
|
||||||
|
oneTime: oneTime,
|
||||||
rowid: rowid,
|
rowid: rowid,
|
||||||
),
|
),
|
||||||
withReferenceMapper: (p0) => p0
|
withReferenceMapper: (p0) => p0
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,12 @@ abstract class AppLocalizations {
|
||||||
Locale('en'),
|
Locale('en'),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// No description provided for @subscriptionAllApps.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Access to all apps'**
|
||||||
|
String get subscriptionAllApps;
|
||||||
|
|
||||||
/// No description provided for @registerSlogan.
|
/// No description provided for @registerSlogan.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -4736,6 +4742,30 @@ abstract class AppLocalizations {
|
||||||
/// **'The app could not be added to this chat.'**
|
/// **'The app could not be added to this chat.'**
|
||||||
String get webxdcStoreFailed;
|
String get webxdcStoreFailed;
|
||||||
|
|
||||||
|
/// No description provided for @webxdcStoreAlreadyAdded.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Already added to this chat'**
|
||||||
|
String get webxdcStoreAlreadyAdded;
|
||||||
|
|
||||||
|
/// No description provided for @webxdcChatAppsMenu.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Chat apps'**
|
||||||
|
String get webxdcChatAppsMenu;
|
||||||
|
|
||||||
|
/// No description provided for @webxdcChatAppsTitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Chat apps'**
|
||||||
|
String get webxdcChatAppsTitle;
|
||||||
|
|
||||||
|
/// No description provided for @webxdcChatAppsEmpty.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'No one-time apps have been added to this chat yet.'**
|
||||||
|
String get webxdcChatAppsEmpty;
|
||||||
|
|
||||||
/// No description provided for @webxdcUnavailable.
|
/// No description provided for @webxdcUnavailable.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import 'app_localizations.dart';
|
||||||
class AppLocalizationsDe extends AppLocalizations {
|
class AppLocalizationsDe extends AppLocalizations {
|
||||||
AppLocalizationsDe([String locale = 'de']) : super(locale);
|
AppLocalizationsDe([String locale = 'de']) : super(locale);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get subscriptionAllApps => 'Zugriff auf alle Apps';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get registerSlogan => 'Privat in Kontakt bleiben.';
|
String get registerSlogan => 'Privat in Kontakt bleiben.';
|
||||||
|
|
||||||
|
|
@ -2754,6 +2757,19 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
String get webxdcStoreFailed =>
|
String get webxdcStoreFailed =>
|
||||||
'Die App konnte diesem Chat nicht hinzugefügt werden.';
|
'Die App konnte diesem Chat nicht hinzugefügt werden.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcStoreAlreadyAdded => 'Bereits zu diesem Chat hinzugefügt';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcChatAppsMenu => 'Chat-Apps';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcChatAppsTitle => 'Chat-Apps';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcChatAppsEmpty =>
|
||||||
|
'Diesem Chat wurden noch keine einmaligen Apps hinzugefügt.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get webxdcUnavailable => 'Diese App konnte nicht geladen werden.';
|
String get webxdcUnavailable => 'Diese App konnte nicht geladen werden.';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import 'app_localizations.dart';
|
||||||
class AppLocalizationsEn extends AppLocalizations {
|
class AppLocalizationsEn extends AppLocalizations {
|
||||||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get subscriptionAllApps => 'Access to all apps';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get registerSlogan => 'Stay in touch privately.';
|
String get registerSlogan => 'Stay in touch privately.';
|
||||||
|
|
||||||
|
|
@ -2726,6 +2729,19 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get webxdcStoreFailed => 'The app could not be added to this chat.';
|
String get webxdcStoreFailed => 'The app could not be added to this chat.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcStoreAlreadyAdded => 'Already added to this chat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcChatAppsMenu => 'Chat apps';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcChatAppsTitle => 'Chat apps';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get webxdcChatAppsEmpty =>
|
||||||
|
'No one-time apps have been added to this chat yet.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get webxdcUnavailable => 'This app could not be loaded.';
|
String get webxdcUnavailable => 'This app could not be loaded.';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"subscriptionAllApps": "Zugriff auf alle Apps",
|
||||||
"@@locale": "de",
|
"@@locale": "de",
|
||||||
"registerSlogan": "Privat in Kontakt bleiben.",
|
"registerSlogan": "Privat in Kontakt bleiben.",
|
||||||
"onboardingWelcomeTitle": "Willkommen bei twonly!",
|
"onboardingWelcomeTitle": "Willkommen bei twonly!",
|
||||||
|
|
@ -1037,6 +1038,10 @@
|
||||||
"webxdcStoreEmpty": "Es sind noch keine Apps verfügbar.",
|
"webxdcStoreEmpty": "Es sind noch keine Apps verfügbar.",
|
||||||
"webxdcStoreOffline": "Die App-Liste konnte nicht geladen werden. Prüfe deine Verbindung und versuche es erneut.",
|
"webxdcStoreOffline": "Die App-Liste konnte nicht geladen werden. Prüfe deine Verbindung und versuche es erneut.",
|
||||||
"webxdcStoreFailed": "Die App konnte diesem Chat nicht hinzugefügt werden.",
|
"webxdcStoreFailed": "Die App konnte diesem Chat nicht hinzugefügt werden.",
|
||||||
|
"webxdcStoreAlreadyAdded": "Bereits zu diesem Chat hinzugefügt",
|
||||||
|
"webxdcChatAppsMenu": "Chat-Apps",
|
||||||
|
"webxdcChatAppsTitle": "Chat-Apps",
|
||||||
|
"webxdcChatAppsEmpty": "Diesem Chat wurden noch keine einmaligen Apps hinzugefügt.",
|
||||||
"webxdcUnavailable": "Diese App konnte nicht geladen werden.",
|
"webxdcUnavailable": "Diese App konnte nicht geladen werden.",
|
||||||
"webxdcDeleteConfirm": "Alles, was diese App auf diesem Gerät gespeichert hat, wird gelöscht. Andere Mitglieder behalten ihre eigene Kopie.",
|
"webxdcDeleteConfirm": "Alles, was diese App auf diesem Gerät gespeichert hat, wird gelöscht. Andere Mitglieder behalten ihre eigene Kopie.",
|
||||||
"webxdcExternalLinkTitle": "twonly verlassen?",
|
"webxdcExternalLinkTitle": "twonly verlassen?",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"subscriptionAllApps": "Access to all apps",
|
||||||
"@@locale": "en",
|
"@@locale": "en",
|
||||||
"registerSlogan": "Stay in touch privately.",
|
"registerSlogan": "Stay in touch privately.",
|
||||||
"onboardingWelcomeTitle": "Welcome to twonly!",
|
"onboardingWelcomeTitle": "Welcome to twonly!",
|
||||||
|
|
@ -1047,6 +1048,10 @@
|
||||||
"webxdcStoreEmpty": "No apps are available yet.",
|
"webxdcStoreEmpty": "No apps are available yet.",
|
||||||
"webxdcStoreOffline": "The app list could not be loaded. Check your connection and try again.",
|
"webxdcStoreOffline": "The app list could not be loaded. Check your connection and try again.",
|
||||||
"webxdcStoreFailed": "The app could not be added to this chat.",
|
"webxdcStoreFailed": "The app could not be added to this chat.",
|
||||||
|
"webxdcStoreAlreadyAdded": "Already added to this chat",
|
||||||
|
"webxdcChatAppsMenu": "Chat apps",
|
||||||
|
"webxdcChatAppsTitle": "Chat apps",
|
||||||
|
"webxdcChatAppsEmpty": "No one-time apps have been added to this chat yet.",
|
||||||
"webxdcUnavailable": "This app could not be loaded.",
|
"webxdcUnavailable": "This app could not be loaded.",
|
||||||
"webxdcDeleteConfirm": "Everything this app saved on this device is deleted. Other members keep their own copy.",
|
"webxdcDeleteConfirm": "Everything this app saved on this device is deleted. Other members keep their own copy.",
|
||||||
"webxdcExternalLinkTitle": "Leave twonly?",
|
"webxdcExternalLinkTitle": "Leave twonly?",
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ class AdditionalMessageData extends $pb.GeneratedMessage {
|
||||||
WebxdcApp? webxdcApp,
|
WebxdcApp? webxdcApp,
|
||||||
WebxdcUpdate? webxdcUpdate,
|
WebxdcUpdate? webxdcUpdate,
|
||||||
WebxdcOrigin? webxdcOrigin,
|
WebxdcOrigin? webxdcOrigin,
|
||||||
|
WebxdcSyncChunk? webxdcSync,
|
||||||
|
WebxdcSyncRequest? webxdcSyncRequest,
|
||||||
}) {
|
}) {
|
||||||
final result = create();
|
final result = create();
|
||||||
if (type != null) result.type = type;
|
if (type != null) result.type = type;
|
||||||
|
|
@ -120,6 +122,8 @@ class AdditionalMessageData extends $pb.GeneratedMessage {
|
||||||
if (webxdcApp != null) result.webxdcApp = webxdcApp;
|
if (webxdcApp != null) result.webxdcApp = webxdcApp;
|
||||||
if (webxdcUpdate != null) result.webxdcUpdate = webxdcUpdate;
|
if (webxdcUpdate != null) result.webxdcUpdate = webxdcUpdate;
|
||||||
if (webxdcOrigin != null) result.webxdcOrigin = webxdcOrigin;
|
if (webxdcOrigin != null) result.webxdcOrigin = webxdcOrigin;
|
||||||
|
if (webxdcSync != null) result.webxdcSync = webxdcSync;
|
||||||
|
if (webxdcSyncRequest != null) result.webxdcSyncRequest = webxdcSyncRequest;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,6 +152,10 @@ class AdditionalMessageData extends $pb.GeneratedMessage {
|
||||||
subBuilder: WebxdcUpdate.create)
|
subBuilder: WebxdcUpdate.create)
|
||||||
..aOM<WebxdcOrigin>(8, _omitFieldNames ? '' : 'webxdcOrigin',
|
..aOM<WebxdcOrigin>(8, _omitFieldNames ? '' : 'webxdcOrigin',
|
||||||
subBuilder: WebxdcOrigin.create)
|
subBuilder: WebxdcOrigin.create)
|
||||||
|
..aOM<WebxdcSyncChunk>(9, _omitFieldNames ? '' : 'webxdcSync',
|
||||||
|
subBuilder: WebxdcSyncChunk.create)
|
||||||
|
..aOM<WebxdcSyncRequest>(10, _omitFieldNames ? '' : 'webxdcSyncRequest',
|
||||||
|
subBuilder: WebxdcSyncRequest.create)
|
||||||
..hasRequiredFields = false;
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
|
@ -241,6 +249,464 @@ class AdditionalMessageData extends $pb.GeneratedMessage {
|
||||||
void clearWebxdcOrigin() => $_clearField(8);
|
void clearWebxdcOrigin() => $_clearField(8);
|
||||||
@$pb.TagNumber(8)
|
@$pb.TagNumber(8)
|
||||||
WebxdcOrigin ensureWebxdcOrigin() => $_ensure(7);
|
WebxdcOrigin ensureWebxdcOrigin() => $_ensure(7);
|
||||||
|
|
||||||
|
@$pb.TagNumber(9)
|
||||||
|
WebxdcSyncChunk get webxdcSync => $_getN(8);
|
||||||
|
@$pb.TagNumber(9)
|
||||||
|
set webxdcSync(WebxdcSyncChunk value) => $_setField(9, value);
|
||||||
|
@$pb.TagNumber(9)
|
||||||
|
$core.bool hasWebxdcSync() => $_has(8);
|
||||||
|
@$pb.TagNumber(9)
|
||||||
|
void clearWebxdcSync() => $_clearField(9);
|
||||||
|
@$pb.TagNumber(9)
|
||||||
|
WebxdcSyncChunk ensureWebxdcSync() => $_ensure(8);
|
||||||
|
|
||||||
|
@$pb.TagNumber(10)
|
||||||
|
WebxdcSyncRequest get webxdcSyncRequest => $_getN(9);
|
||||||
|
@$pb.TagNumber(10)
|
||||||
|
set webxdcSyncRequest(WebxdcSyncRequest value) => $_setField(10, value);
|
||||||
|
@$pb.TagNumber(10)
|
||||||
|
$core.bool hasWebxdcSyncRequest() => $_has(9);
|
||||||
|
@$pb.TagNumber(10)
|
||||||
|
void clearWebxdcSyncRequest() => $_clearField(10);
|
||||||
|
@$pb.TagNumber(10)
|
||||||
|
WebxdcSyncRequest ensureWebxdcSyncRequest() => $_ensure(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A peer-to-peer transfer of existing one-time app state. The encoded payload
|
||||||
|
/// is split into bounded hidden messages and installed only after every chunk
|
||||||
|
/// arrived and the digest matches.
|
||||||
|
class WebxdcSyncChunk extends $pb.GeneratedMessage {
|
||||||
|
factory WebxdcSyncChunk({
|
||||||
|
$core.String? transferId,
|
||||||
|
$core.int? chunkIndex,
|
||||||
|
$core.int? chunkCount,
|
||||||
|
$core.List<$core.int>? payloadSha256,
|
||||||
|
$core.List<$core.int>? payload,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (transferId != null) result.transferId = transferId;
|
||||||
|
if (chunkIndex != null) result.chunkIndex = chunkIndex;
|
||||||
|
if (chunkCount != null) result.chunkCount = chunkCount;
|
||||||
|
if (payloadSha256 != null) result.payloadSha256 = payloadSha256;
|
||||||
|
if (payload != null) result.payload = payload;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebxdcSyncChunk._();
|
||||||
|
|
||||||
|
factory WebxdcSyncChunk.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory WebxdcSyncChunk.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'WebxdcSyncChunk',
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..aOS(1, _omitFieldNames ? '' : 'transferId')
|
||||||
|
..aI(2, _omitFieldNames ? '' : 'chunkIndex', fieldType: $pb.PbFieldType.OU3)
|
||||||
|
..aI(3, _omitFieldNames ? '' : 'chunkCount', fieldType: $pb.PbFieldType.OU3)
|
||||||
|
..a<$core.List<$core.int>>(
|
||||||
|
4, _omitFieldNames ? '' : 'payloadSha256', $pb.PbFieldType.OY)
|
||||||
|
..a<$core.List<$core.int>>(
|
||||||
|
5, _omitFieldNames ? '' : 'payload', $pb.PbFieldType.OY)
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncChunk clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncChunk copyWith(void Function(WebxdcSyncChunk) updates) =>
|
||||||
|
super.copyWith((message) => updates(message as WebxdcSyncChunk))
|
||||||
|
as WebxdcSyncChunk;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncChunk create() => WebxdcSyncChunk._();
|
||||||
|
@$core.override
|
||||||
|
WebxdcSyncChunk createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncChunk getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<WebxdcSyncChunk>(create);
|
||||||
|
static WebxdcSyncChunk? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.String get transferId => $_getSZ(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set transferId($core.String value) => $_setString(0, value);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasTransferId() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearTransferId() => $_clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.int get chunkIndex => $_getIZ(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set chunkIndex($core.int value) => $_setUnsignedInt32(1, value);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasChunkIndex() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearChunkIndex() => $_clearField(2);
|
||||||
|
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.int get chunkCount => $_getIZ(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
set chunkCount($core.int value) => $_setUnsignedInt32(2, value);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.bool hasChunkCount() => $_has(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
void clearChunkCount() => $_clearField(3);
|
||||||
|
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.List<$core.int> get payloadSha256 => $_getN(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
set payloadSha256($core.List<$core.int> value) => $_setBytes(3, value);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.bool hasPayloadSha256() => $_has(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
void clearPayloadSha256() => $_clearField(4);
|
||||||
|
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.List<$core.int> get payload => $_getN(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
set payload($core.List<$core.int> value) => $_setBytes(4, value);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.bool hasPayload() => $_has(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
void clearPayload() => $_clearField(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebxdcSyncRequest extends $pb.GeneratedMessage {
|
||||||
|
factory WebxdcSyncRequest() => create();
|
||||||
|
|
||||||
|
WebxdcSyncRequest._();
|
||||||
|
|
||||||
|
factory WebxdcSyncRequest.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory WebxdcSyncRequest.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'WebxdcSyncRequest',
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncRequest clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncRequest copyWith(void Function(WebxdcSyncRequest) updates) =>
|
||||||
|
super.copyWith((message) => updates(message as WebxdcSyncRequest))
|
||||||
|
as WebxdcSyncRequest;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncRequest create() => WebxdcSyncRequest._();
|
||||||
|
@$core.override
|
||||||
|
WebxdcSyncRequest createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncRequest getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<WebxdcSyncRequest>(create);
|
||||||
|
static WebxdcSyncRequest? _defaultInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebxdcSyncPayload extends $pb.GeneratedMessage {
|
||||||
|
factory WebxdcSyncPayload({
|
||||||
|
$core.Iterable<WebxdcSyncInstance>? instances,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (instances != null) result.instances.addAll(instances);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebxdcSyncPayload._();
|
||||||
|
|
||||||
|
factory WebxdcSyncPayload.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory WebxdcSyncPayload.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'WebxdcSyncPayload',
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..pPM<WebxdcSyncInstance>(1, _omitFieldNames ? '' : 'instances',
|
||||||
|
subBuilder: WebxdcSyncInstance.create)
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncPayload clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncPayload copyWith(void Function(WebxdcSyncPayload) updates) =>
|
||||||
|
super.copyWith((message) => updates(message as WebxdcSyncPayload))
|
||||||
|
as WebxdcSyncPayload;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncPayload create() => WebxdcSyncPayload._();
|
||||||
|
@$core.override
|
||||||
|
WebxdcSyncPayload createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncPayload getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<WebxdcSyncPayload>(create);
|
||||||
|
static WebxdcSyncPayload? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$pb.PbList<WebxdcSyncInstance> get instances => $_getList(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebxdcSyncInstance extends $pb.GeneratedMessage {
|
||||||
|
factory WebxdcSyncInstance({
|
||||||
|
$core.String? instanceId,
|
||||||
|
$core.String? appId,
|
||||||
|
$fixnum.Int64? version,
|
||||||
|
$core.String? summary,
|
||||||
|
$core.String? document,
|
||||||
|
$fixnum.Int64? createdAt,
|
||||||
|
$fixnum.Int64? lastUpdateAt,
|
||||||
|
$core.Iterable<WebxdcSyncUpdate>? updates,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (instanceId != null) result.instanceId = instanceId;
|
||||||
|
if (appId != null) result.appId = appId;
|
||||||
|
if (version != null) result.version = version;
|
||||||
|
if (summary != null) result.summary = summary;
|
||||||
|
if (document != null) result.document = document;
|
||||||
|
if (createdAt != null) result.createdAt = createdAt;
|
||||||
|
if (lastUpdateAt != null) result.lastUpdateAt = lastUpdateAt;
|
||||||
|
if (updates != null) result.updates.addAll(updates);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebxdcSyncInstance._();
|
||||||
|
|
||||||
|
factory WebxdcSyncInstance.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory WebxdcSyncInstance.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'WebxdcSyncInstance',
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..aOS(1, _omitFieldNames ? '' : 'instanceId')
|
||||||
|
..aOS(2, _omitFieldNames ? '' : 'appId')
|
||||||
|
..aInt64(3, _omitFieldNames ? '' : 'version')
|
||||||
|
..aOS(4, _omitFieldNames ? '' : 'summary')
|
||||||
|
..aOS(5, _omitFieldNames ? '' : 'document')
|
||||||
|
..aInt64(6, _omitFieldNames ? '' : 'createdAt')
|
||||||
|
..aInt64(7, _omitFieldNames ? '' : 'lastUpdateAt')
|
||||||
|
..pPM<WebxdcSyncUpdate>(8, _omitFieldNames ? '' : 'updates',
|
||||||
|
subBuilder: WebxdcSyncUpdate.create)
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncInstance clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncInstance copyWith(void Function(WebxdcSyncInstance) updates) =>
|
||||||
|
super.copyWith((message) => updates(message as WebxdcSyncInstance))
|
||||||
|
as WebxdcSyncInstance;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncInstance create() => WebxdcSyncInstance._();
|
||||||
|
@$core.override
|
||||||
|
WebxdcSyncInstance createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncInstance getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<WebxdcSyncInstance>(create);
|
||||||
|
static WebxdcSyncInstance? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.String get instanceId => $_getSZ(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set instanceId($core.String value) => $_setString(0, value);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasInstanceId() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearInstanceId() => $_clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.String get appId => $_getSZ(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set appId($core.String value) => $_setString(1, value);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasAppId() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearAppId() => $_clearField(2);
|
||||||
|
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$fixnum.Int64 get version => $_getI64(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
set version($fixnum.Int64 value) => $_setInt64(2, value);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.bool hasVersion() => $_has(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
void clearVersion() => $_clearField(3);
|
||||||
|
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.String get summary => $_getSZ(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
set summary($core.String value) => $_setString(3, value);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.bool hasSummary() => $_has(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
void clearSummary() => $_clearField(4);
|
||||||
|
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.String get document => $_getSZ(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
set document($core.String value) => $_setString(4, value);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.bool hasDocument() => $_has(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
void clearDocument() => $_clearField(5);
|
||||||
|
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
$fixnum.Int64 get createdAt => $_getI64(5);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
set createdAt($fixnum.Int64 value) => $_setInt64(5, value);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
$core.bool hasCreatedAt() => $_has(5);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
void clearCreatedAt() => $_clearField(6);
|
||||||
|
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
$fixnum.Int64 get lastUpdateAt => $_getI64(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
set lastUpdateAt($fixnum.Int64 value) => $_setInt64(6, value);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
$core.bool hasLastUpdateAt() => $_has(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
void clearLastUpdateAt() => $_clearField(7);
|
||||||
|
|
||||||
|
@$pb.TagNumber(8)
|
||||||
|
$pb.PbList<WebxdcSyncUpdate> get updates => $_getList(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebxdcSyncUpdate extends $pb.GeneratedMessage {
|
||||||
|
factory WebxdcSyncUpdate({
|
||||||
|
$core.String? messageId,
|
||||||
|
$fixnum.Int64? senderId,
|
||||||
|
$core.String? payload,
|
||||||
|
$core.String? info,
|
||||||
|
$core.String? href,
|
||||||
|
$fixnum.Int64? receivedAt,
|
||||||
|
}) {
|
||||||
|
final result = create();
|
||||||
|
if (messageId != null) result.messageId = messageId;
|
||||||
|
if (senderId != null) result.senderId = senderId;
|
||||||
|
if (payload != null) result.payload = payload;
|
||||||
|
if (info != null) result.info = info;
|
||||||
|
if (href != null) result.href = href;
|
||||||
|
if (receivedAt != null) result.receivedAt = receivedAt;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebxdcSyncUpdate._();
|
||||||
|
|
||||||
|
factory WebxdcSyncUpdate.fromBuffer($core.List<$core.int> data,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromBuffer(data, registry);
|
||||||
|
factory WebxdcSyncUpdate.fromJson($core.String json,
|
||||||
|
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||||
|
create()..mergeFromJson(json, registry);
|
||||||
|
|
||||||
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||||
|
_omitMessageNames ? '' : 'WebxdcSyncUpdate',
|
||||||
|
createEmptyInstance: create)
|
||||||
|
..aOS(1, _omitFieldNames ? '' : 'messageId')
|
||||||
|
..aInt64(2, _omitFieldNames ? '' : 'senderId')
|
||||||
|
..aOS(3, _omitFieldNames ? '' : 'payload')
|
||||||
|
..aOS(4, _omitFieldNames ? '' : 'info')
|
||||||
|
..aOS(5, _omitFieldNames ? '' : 'href')
|
||||||
|
..aInt64(6, _omitFieldNames ? '' : 'receivedAt')
|
||||||
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncUpdate clone() => deepCopy();
|
||||||
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
WebxdcSyncUpdate copyWith(void Function(WebxdcSyncUpdate) updates) =>
|
||||||
|
super.copyWith((message) => updates(message as WebxdcSyncUpdate))
|
||||||
|
as WebxdcSyncUpdate;
|
||||||
|
|
||||||
|
@$core.override
|
||||||
|
$pb.BuilderInfo get info_ => _i;
|
||||||
|
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncUpdate create() => WebxdcSyncUpdate._();
|
||||||
|
@$core.override
|
||||||
|
WebxdcSyncUpdate createEmptyInstance() => create();
|
||||||
|
@$core.pragma('dart2js:noInline')
|
||||||
|
static WebxdcSyncUpdate getDefault() => _defaultInstance ??=
|
||||||
|
$pb.GeneratedMessage.$_defaultFor<WebxdcSyncUpdate>(create);
|
||||||
|
static WebxdcSyncUpdate? _defaultInstance;
|
||||||
|
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.String get messageId => $_getSZ(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
set messageId($core.String value) => $_setString(0, value);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
$core.bool hasMessageId() => $_has(0);
|
||||||
|
@$pb.TagNumber(1)
|
||||||
|
void clearMessageId() => $_clearField(1);
|
||||||
|
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$fixnum.Int64 get senderId => $_getI64(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
set senderId($fixnum.Int64 value) => $_setInt64(1, value);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
$core.bool hasSenderId() => $_has(1);
|
||||||
|
@$pb.TagNumber(2)
|
||||||
|
void clearSenderId() => $_clearField(2);
|
||||||
|
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.String get payload => $_getSZ(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
set payload($core.String value) => $_setString(2, value);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
$core.bool hasPayload() => $_has(2);
|
||||||
|
@$pb.TagNumber(3)
|
||||||
|
void clearPayload() => $_clearField(3);
|
||||||
|
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.String get info => $_getSZ(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
set info($core.String value) => $_setString(3, value);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
$core.bool hasInfo() => $_has(3);
|
||||||
|
@$pb.TagNumber(4)
|
||||||
|
void clearInfo() => $_clearField(4);
|
||||||
|
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.String get href => $_getSZ(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
set href($core.String value) => $_setString(4, value);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
$core.bool hasHref() => $_has(4);
|
||||||
|
@$pb.TagNumber(5)
|
||||||
|
void clearHref() => $_clearField(5);
|
||||||
|
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
$fixnum.Int64 get receivedAt => $_getI64(5);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
set receivedAt($fixnum.Int64 value) => $_setInt64(5, value);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
$core.bool hasReceivedAt() => $_has(5);
|
||||||
|
@$pb.TagNumber(6)
|
||||||
|
void clearReceivedAt() => $_clearField(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attached to a message a webxdc app asked the user to send, so the chat can
|
/// Attached to a message a webxdc app asked the user to send, so the chat can
|
||||||
|
|
@ -402,6 +868,7 @@ class WebxdcUpdate extends $pb.GeneratedMessage {
|
||||||
$core.String? href,
|
$core.String? href,
|
||||||
$core.String? summary,
|
$core.String? summary,
|
||||||
$core.String? document,
|
$core.String? document,
|
||||||
|
$core.String? notify,
|
||||||
}) {
|
}) {
|
||||||
final result = create();
|
final result = create();
|
||||||
if (instanceId != null) result.instanceId = instanceId;
|
if (instanceId != null) result.instanceId = instanceId;
|
||||||
|
|
@ -410,6 +877,7 @@ class WebxdcUpdate extends $pb.GeneratedMessage {
|
||||||
if (href != null) result.href = href;
|
if (href != null) result.href = href;
|
||||||
if (summary != null) result.summary = summary;
|
if (summary != null) result.summary = summary;
|
||||||
if (document != null) result.document = document;
|
if (document != null) result.document = document;
|
||||||
|
if (notify != null) result.notify = notify;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,6 +899,7 @@ class WebxdcUpdate extends $pb.GeneratedMessage {
|
||||||
..aOS(4, _omitFieldNames ? '' : 'href')
|
..aOS(4, _omitFieldNames ? '' : 'href')
|
||||||
..aOS(5, _omitFieldNames ? '' : 'summary')
|
..aOS(5, _omitFieldNames ? '' : 'summary')
|
||||||
..aOS(6, _omitFieldNames ? '' : 'document')
|
..aOS(6, _omitFieldNames ? '' : 'document')
|
||||||
|
..aOS(7, _omitFieldNames ? '' : 'notify')
|
||||||
..hasRequiredFields = false;
|
..hasRequiredFields = false;
|
||||||
|
|
||||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||||
|
|
@ -507,6 +976,17 @@ class WebxdcUpdate extends $pb.GeneratedMessage {
|
||||||
$core.bool hasDocument() => $_has(5);
|
$core.bool hasDocument() => $_has(5);
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
void clearDocument() => $_clearField(6);
|
void clearDocument() => $_clearField(6);
|
||||||
|
|
||||||
|
/// JSON map of app-scoped member addresses to notification text.
|
||||||
|
/// Absent preserves legacy broadcast; an empty map notifies nobody.
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
$core.String get notify => $_getSZ(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
set notify($core.String value) => $_setString(6, value);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
$core.bool hasNotify() => $_has(6);
|
||||||
|
@$pb.TagNumber(7)
|
||||||
|
void clearNotify() => $_clearField(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
const $core.bool _omitFieldNames =
|
const $core.bool _omitFieldNames =
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ class AdditionalMessageData_Type extends $pb.ProtobufEnum {
|
||||||
AdditionalMessageData_Type._(5, _omitEnumNames ? '' : 'WEBXDC_UPDATE');
|
AdditionalMessageData_Type._(5, _omitEnumNames ? '' : 'WEBXDC_UPDATE');
|
||||||
static const AdditionalMessageData_Type WEBXDC_SENT =
|
static const AdditionalMessageData_Type WEBXDC_SENT =
|
||||||
AdditionalMessageData_Type._(6, _omitEnumNames ? '' : 'WEBXDC_SENT');
|
AdditionalMessageData_Type._(6, _omitEnumNames ? '' : 'WEBXDC_SENT');
|
||||||
|
static const AdditionalMessageData_Type WEBXDC_SYNC =
|
||||||
|
AdditionalMessageData_Type._(7, _omitEnumNames ? '' : 'WEBXDC_SYNC');
|
||||||
|
static const AdditionalMessageData_Type WEBXDC_SYNC_REQUEST =
|
||||||
|
AdditionalMessageData_Type._(
|
||||||
|
8, _omitEnumNames ? '' : 'WEBXDC_SYNC_REQUEST');
|
||||||
|
|
||||||
static const $core.List<AdditionalMessageData_Type> values =
|
static const $core.List<AdditionalMessageData_Type> values =
|
||||||
<AdditionalMessageData_Type>[
|
<AdditionalMessageData_Type>[
|
||||||
|
|
@ -40,10 +45,12 @@ class AdditionalMessageData_Type extends $pb.ProtobufEnum {
|
||||||
WEBXDC_APP,
|
WEBXDC_APP,
|
||||||
WEBXDC_UPDATE,
|
WEBXDC_UPDATE,
|
||||||
WEBXDC_SENT,
|
WEBXDC_SENT,
|
||||||
|
WEBXDC_SYNC,
|
||||||
|
WEBXDC_SYNC_REQUEST,
|
||||||
];
|
];
|
||||||
|
|
||||||
static final $core.List<AdditionalMessageData_Type?> _byValue =
|
static final $core.List<AdditionalMessageData_Type?> _byValue =
|
||||||
$pb.ProtobufEnum.$_initByValueList(values, 6);
|
$pb.ProtobufEnum.$_initByValueList(values, 8);
|
||||||
static AdditionalMessageData_Type? valueOf($core.int value) =>
|
static AdditionalMessageData_Type? valueOf($core.int value) =>
|
||||||
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,26 @@ const AdditionalMessageData$json = {
|
||||||
'10': 'webxdcOrigin',
|
'10': 'webxdcOrigin',
|
||||||
'17': true
|
'17': true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'1': 'webxdc_sync',
|
||||||
|
'3': 9,
|
||||||
|
'4': 1,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.WebxdcSyncChunk',
|
||||||
|
'9': 6,
|
||||||
|
'10': 'webxdcSync',
|
||||||
|
'17': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'1': 'webxdc_sync_request',
|
||||||
|
'3': 10,
|
||||||
|
'4': 1,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.WebxdcSyncRequest',
|
||||||
|
'9': 7,
|
||||||
|
'10': 'webxdcSyncRequest',
|
||||||
|
'17': true
|
||||||
|
},
|
||||||
],
|
],
|
||||||
'4': [AdditionalMessageData_Type$json],
|
'4': [AdditionalMessageData_Type$json],
|
||||||
'8': [
|
'8': [
|
||||||
|
|
@ -115,6 +135,8 @@ const AdditionalMessageData$json = {
|
||||||
{'1': '_webxdc_app'},
|
{'1': '_webxdc_app'},
|
||||||
{'1': '_webxdc_update'},
|
{'1': '_webxdc_update'},
|
||||||
{'1': '_webxdc_origin'},
|
{'1': '_webxdc_origin'},
|
||||||
|
{'1': '_webxdc_sync'},
|
||||||
|
{'1': '_webxdc_sync_request'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -129,6 +151,8 @@ const AdditionalMessageData_Type$json = {
|
||||||
{'1': 'WEBXDC_APP', '2': 4},
|
{'1': 'WEBXDC_APP', '2': 4},
|
||||||
{'1': 'WEBXDC_UPDATE', '2': 5},
|
{'1': 'WEBXDC_UPDATE', '2': 5},
|
||||||
{'1': 'WEBXDC_SENT', '2': 6},
|
{'1': 'WEBXDC_SENT', '2': 6},
|
||||||
|
{'1': 'WEBXDC_SYNC', '2': 7},
|
||||||
|
{'1': 'WEBXDC_SYNC_REQUEST', '2': 8},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -141,11 +165,148 @@ final $typed_data.Uint8List additionalMessageDataDescriptor = $convert.base64Dec
|
||||||
'BSABKANIAlIOYXNrQWJvdXRVc2VySWSIAQESLgoKd2VieGRjX2FwcBgGIAEoCzIKLldlYnhkY0'
|
'BSABKANIAlIOYXNrQWJvdXRVc2VySWSIAQESLgoKd2VieGRjX2FwcBgGIAEoCzIKLldlYnhkY0'
|
||||||
'FwcEgDUgl3ZWJ4ZGNBcHCIAQESNwoNd2VieGRjX3VwZGF0ZRgHIAEoCzINLldlYnhkY1VwZGF0'
|
'FwcEgDUgl3ZWJ4ZGNBcHCIAQESNwoNd2VieGRjX3VwZGF0ZRgHIAEoCzINLldlYnhkY1VwZGF0'
|
||||||
'ZUgEUgx3ZWJ4ZGNVcGRhdGWIAQESNwoNd2VieGRjX29yaWdpbhgIIAEoCzINLldlYnhkY09yaW'
|
'ZUgEUgx3ZWJ4ZGNVcGRhdGWIAQESNwoNd2VieGRjX29yaWdpbhgIIAEoCzINLldlYnhkY09yaW'
|
||||||
'dpbkgFUgx3ZWJ4ZGNPcmlnaW6IAQEiggEKBFR5cGUSCAoETElOSxAAEgwKCENPTlRBQ1RTEAES'
|
'dpbkgFUgx3ZWJ4ZGNPcmlnaW6IAQESNgoLd2VieGRjX3N5bmMYCSABKAsyEC5XZWJ4ZGNTeW5j'
|
||||||
'GgoWUkVTVE9SRURfRkxBTUVfQ09VTlRFUhACEhIKDkFTS19BQk9VVF9VU0VSEAMSDgoKV0VCWE'
|
'Q2h1bmtIBlIKd2VieGRjU3luY4gBARJHChN3ZWJ4ZGNfc3luY19yZXF1ZXN0GAogASgLMhIuV2'
|
||||||
'RDX0FQUBAEEhEKDVdFQlhEQ19VUERBVEUQBRIPCgtXRUJYRENfU0VOVBAGQgcKBV9saW5rQhkK'
|
'VieGRjU3luY1JlcXVlc3RIB1IRd2VieGRjU3luY1JlcXVlc3SIAQEirAEKBFR5cGUSCAoETElO'
|
||||||
'F19yZXN0b3JlZF9mbGFtZV9jb3VudGVyQhQKEl9hc2tfYWJvdXRfdXNlcl9pZEINCgtfd2VieG'
|
'SxAAEgwKCENPTlRBQ1RTEAESGgoWUkVTVE9SRURfRkxBTUVfQ09VTlRFUhACEhIKDkFTS19BQk'
|
||||||
'RjX2FwcEIQCg5fd2VieGRjX3VwZGF0ZUIQCg5fd2VieGRjX29yaWdpbg==');
|
'9VVF9VU0VSEAMSDgoKV0VCWERDX0FQUBAEEhEKDVdFQlhEQ19VUERBVEUQBRIPCgtXRUJYRENf'
|
||||||
|
'U0VOVBAGEg8KC1dFQlhEQ19TWU5DEAcSFwoTV0VCWERDX1NZTkNfUkVRVUVTVBAIQgcKBV9saW'
|
||||||
|
'5rQhkKF19yZXN0b3JlZF9mbGFtZV9jb3VudGVyQhQKEl9hc2tfYWJvdXRfdXNlcl9pZEINCgtf'
|
||||||
|
'd2VieGRjX2FwcEIQCg5fd2VieGRjX3VwZGF0ZUIQCg5fd2VieGRjX29yaWdpbkIOCgxfd2VieG'
|
||||||
|
'RjX3N5bmNCFgoUX3dlYnhkY19zeW5jX3JlcXVlc3Q=');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use webxdcSyncChunkDescriptor instead')
|
||||||
|
const WebxdcSyncChunk$json = {
|
||||||
|
'1': 'WebxdcSyncChunk',
|
||||||
|
'2': [
|
||||||
|
{'1': 'transfer_id', '3': 1, '4': 1, '5': 9, '10': 'transferId'},
|
||||||
|
{'1': 'chunk_index', '3': 2, '4': 1, '5': 13, '10': 'chunkIndex'},
|
||||||
|
{'1': 'chunk_count', '3': 3, '4': 1, '5': 13, '10': 'chunkCount'},
|
||||||
|
{'1': 'payload_sha256', '3': 4, '4': 1, '5': 12, '10': 'payloadSha256'},
|
||||||
|
{'1': 'payload', '3': 5, '4': 1, '5': 12, '10': 'payload'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `WebxdcSyncChunk`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List webxdcSyncChunkDescriptor = $convert.base64Decode(
|
||||||
|
'Cg9XZWJ4ZGNTeW5jQ2h1bmsSHwoLdHJhbnNmZXJfaWQYASABKAlSCnRyYW5zZmVySWQSHwoLY2'
|
||||||
|
'h1bmtfaW5kZXgYAiABKA1SCmNodW5rSW5kZXgSHwoLY2h1bmtfY291bnQYAyABKA1SCmNodW5r'
|
||||||
|
'Q291bnQSJQoOcGF5bG9hZF9zaGEyNTYYBCABKAxSDXBheWxvYWRTaGEyNTYSGAoHcGF5bG9hZB'
|
||||||
|
'gFIAEoDFIHcGF5bG9hZA==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use webxdcSyncRequestDescriptor instead')
|
||||||
|
const WebxdcSyncRequest$json = {
|
||||||
|
'1': 'WebxdcSyncRequest',
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `WebxdcSyncRequest`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List webxdcSyncRequestDescriptor =
|
||||||
|
$convert.base64Decode('ChFXZWJ4ZGNTeW5jUmVxdWVzdA==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use webxdcSyncPayloadDescriptor instead')
|
||||||
|
const WebxdcSyncPayload$json = {
|
||||||
|
'1': 'WebxdcSyncPayload',
|
||||||
|
'2': [
|
||||||
|
{
|
||||||
|
'1': 'instances',
|
||||||
|
'3': 1,
|
||||||
|
'4': 3,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.WebxdcSyncInstance',
|
||||||
|
'10': 'instances'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `WebxdcSyncPayload`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List webxdcSyncPayloadDescriptor = $convert.base64Decode(
|
||||||
|
'ChFXZWJ4ZGNTeW5jUGF5bG9hZBIxCglpbnN0YW5jZXMYASADKAsyEy5XZWJ4ZGNTeW5jSW5zdG'
|
||||||
|
'FuY2VSCWluc3RhbmNlcw==');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use webxdcSyncInstanceDescriptor instead')
|
||||||
|
const WebxdcSyncInstance$json = {
|
||||||
|
'1': 'WebxdcSyncInstance',
|
||||||
|
'2': [
|
||||||
|
{'1': 'instance_id', '3': 1, '4': 1, '5': 9, '10': 'instanceId'},
|
||||||
|
{'1': 'app_id', '3': 2, '4': 1, '5': 9, '10': 'appId'},
|
||||||
|
{'1': 'version', '3': 3, '4': 1, '5': 3, '10': 'version'},
|
||||||
|
{
|
||||||
|
'1': 'summary',
|
||||||
|
'3': 4,
|
||||||
|
'4': 1,
|
||||||
|
'5': 9,
|
||||||
|
'9': 0,
|
||||||
|
'10': 'summary',
|
||||||
|
'17': true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'1': 'document',
|
||||||
|
'3': 5,
|
||||||
|
'4': 1,
|
||||||
|
'5': 9,
|
||||||
|
'9': 1,
|
||||||
|
'10': 'document',
|
||||||
|
'17': true
|
||||||
|
},
|
||||||
|
{'1': 'created_at', '3': 6, '4': 1, '5': 3, '10': 'createdAt'},
|
||||||
|
{'1': 'last_update_at', '3': 7, '4': 1, '5': 3, '10': 'lastUpdateAt'},
|
||||||
|
{
|
||||||
|
'1': 'updates',
|
||||||
|
'3': 8,
|
||||||
|
'4': 3,
|
||||||
|
'5': 11,
|
||||||
|
'6': '.WebxdcSyncUpdate',
|
||||||
|
'10': 'updates'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_summary'},
|
||||||
|
{'1': '_document'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `WebxdcSyncInstance`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List webxdcSyncInstanceDescriptor = $convert.base64Decode(
|
||||||
|
'ChJXZWJ4ZGNTeW5jSW5zdGFuY2USHwoLaW5zdGFuY2VfaWQYASABKAlSCmluc3RhbmNlSWQSFQ'
|
||||||
|
'oGYXBwX2lkGAIgASgJUgVhcHBJZBIYCgd2ZXJzaW9uGAMgASgDUgd2ZXJzaW9uEh0KB3N1bW1h'
|
||||||
|
'cnkYBCABKAlIAFIHc3VtbWFyeYgBARIfCghkb2N1bWVudBgFIAEoCUgBUghkb2N1bWVudIgBAR'
|
||||||
|
'IdCgpjcmVhdGVkX2F0GAYgASgDUgljcmVhdGVkQXQSJAoObGFzdF91cGRhdGVfYXQYByABKANS'
|
||||||
|
'DGxhc3RVcGRhdGVBdBIrCgd1cGRhdGVzGAggAygLMhEuV2VieGRjU3luY1VwZGF0ZVIHdXBkYX'
|
||||||
|
'Rlc0IKCghfc3VtbWFyeUILCglfZG9jdW1lbnQ=');
|
||||||
|
|
||||||
|
@$core.Deprecated('Use webxdcSyncUpdateDescriptor instead')
|
||||||
|
const WebxdcSyncUpdate$json = {
|
||||||
|
'1': 'WebxdcSyncUpdate',
|
||||||
|
'2': [
|
||||||
|
{'1': 'message_id', '3': 1, '4': 1, '5': 9, '10': 'messageId'},
|
||||||
|
{
|
||||||
|
'1': 'sender_id',
|
||||||
|
'3': 2,
|
||||||
|
'4': 1,
|
||||||
|
'5': 3,
|
||||||
|
'9': 0,
|
||||||
|
'10': 'senderId',
|
||||||
|
'17': true
|
||||||
|
},
|
||||||
|
{'1': 'payload', '3': 3, '4': 1, '5': 9, '10': 'payload'},
|
||||||
|
{'1': 'info', '3': 4, '4': 1, '5': 9, '9': 1, '10': 'info', '17': true},
|
||||||
|
{'1': 'href', '3': 5, '4': 1, '5': 9, '9': 2, '10': 'href', '17': true},
|
||||||
|
{'1': 'received_at', '3': 6, '4': 1, '5': 3, '10': 'receivedAt'},
|
||||||
|
],
|
||||||
|
'8': [
|
||||||
|
{'1': '_sender_id'},
|
||||||
|
{'1': '_info'},
|
||||||
|
{'1': '_href'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Descriptor for `WebxdcSyncUpdate`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
|
final $typed_data.Uint8List webxdcSyncUpdateDescriptor = $convert.base64Decode(
|
||||||
|
'ChBXZWJ4ZGNTeW5jVXBkYXRlEh0KCm1lc3NhZ2VfaWQYASABKAlSCW1lc3NhZ2VJZBIgCglzZW'
|
||||||
|
'5kZXJfaWQYAiABKANIAFIIc2VuZGVySWSIAQESGAoHcGF5bG9hZBgDIAEoCVIHcGF5bG9hZBIX'
|
||||||
|
'CgRpbmZvGAQgASgJSAFSBGluZm+IAQESFwoEaHJlZhgFIAEoCUgCUgRocmVmiAEBEh8KC3JlY2'
|
||||||
|
'VpdmVkX2F0GAYgASgDUgpyZWNlaXZlZEF0QgwKCl9zZW5kZXJfaWRCBwoFX2luZm9CBwoFX2hy'
|
||||||
|
'ZWY=');
|
||||||
|
|
||||||
@$core.Deprecated('Use webxdcOriginDescriptor instead')
|
@$core.Deprecated('Use webxdcOriginDescriptor instead')
|
||||||
const WebxdcOrigin$json = {
|
const WebxdcOrigin$json = {
|
||||||
|
|
@ -202,12 +363,14 @@ const WebxdcUpdate$json = {
|
||||||
'10': 'document',
|
'10': 'document',
|
||||||
'17': true
|
'17': true
|
||||||
},
|
},
|
||||||
|
{'1': 'notify', '3': 7, '4': 1, '5': 9, '9': 4, '10': 'notify', '17': true},
|
||||||
],
|
],
|
||||||
'8': [
|
'8': [
|
||||||
{'1': '_info'},
|
{'1': '_info'},
|
||||||
{'1': '_href'},
|
{'1': '_href'},
|
||||||
{'1': '_summary'},
|
{'1': '_summary'},
|
||||||
{'1': '_document'},
|
{'1': '_document'},
|
||||||
|
{'1': '_notify'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -216,5 +379,5 @@ final $typed_data.Uint8List webxdcUpdateDescriptor = $convert.base64Decode(
|
||||||
'CgxXZWJ4ZGNVcGRhdGUSHwoLaW5zdGFuY2VfaWQYASABKAlSCmluc3RhbmNlSWQSGAoHcGF5bG'
|
'CgxXZWJ4ZGNVcGRhdGUSHwoLaW5zdGFuY2VfaWQYASABKAlSCmluc3RhbmNlSWQSGAoHcGF5bG'
|
||||||
'9hZBgCIAEoCVIHcGF5bG9hZBIXCgRpbmZvGAMgASgJSABSBGluZm+IAQESFwoEaHJlZhgEIAEo'
|
'9hZBgCIAEoCVIHcGF5bG9hZBIXCgRpbmZvGAMgASgJSABSBGluZm+IAQESFwoEaHJlZhgEIAEo'
|
||||||
'CUgBUgRocmVmiAEBEh0KB3N1bW1hcnkYBSABKAlIAlIHc3VtbWFyeYgBARIfCghkb2N1bWVudB'
|
'CUgBUgRocmVmiAEBEh0KB3N1bW1hcnkYBSABKAlIAlIHc3VtbWFyeYgBARIfCghkb2N1bWVudB'
|
||||||
'gGIAEoCUgDUghkb2N1bWVudIgBAUIHCgVfaW5mb0IHCgVfaHJlZkIKCghfc3VtbWFyeUILCglf'
|
'gGIAEoCUgDUghkb2N1bWVudIgBARIbCgZub3RpZnkYByABKAlIBFIGbm90aWZ5iAEBQgcKBV9p'
|
||||||
'ZG9jdW1lbnQ=');
|
'bmZvQgcKBV9ocmVmQgoKCF9zdW1tYXJ5QgsKCV9kb2N1bWVudEIJCgdfbm90aWZ5');
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,32 @@ class WebxdcService {
|
||||||
/// cached with all its translations, so choosing one costs nothing and is
|
/// cached with all its translations, so choosing one costs nothing and is
|
||||||
/// never sent anywhere.
|
/// never sent anywhere.
|
||||||
static Future<List<rust_webxdc.WebxdcStoreApp>> catalog(
|
static Future<List<rust_webxdc.WebxdcStoreApp>> catalog(
|
||||||
|
String groupId,
|
||||||
List<String> languages,
|
List<String> languages,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
return await rust_webxdc.catalog(languages: languages);
|
return await rust_webxdc.catalog(groupId: groupId, languages: languages);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Log.warn('reading the webxdc catalog failed: $error');
|
Log.warn('reading the webxdc catalog failed: $error');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<List<rust_webxdc.WebxdcOneTimeInstance>> oneTimeInstances(
|
||||||
|
String groupId,
|
||||||
|
List<String> languages,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
return await rust_webxdc.oneTimeInstances(
|
||||||
|
groupId: groupId,
|
||||||
|
languages: languages,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
Log.warn('reading one-time webxdc apps for $groupId failed: $error');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Places an app into a chat. Returns the id of the message carrying it,
|
/// Places an app into a chat. Returns the id of the message carrying it,
|
||||||
/// which is also the instance id.
|
/// which is also the instance id.
|
||||||
static Future<String?> createInstance(
|
static Future<String?> createInstance(
|
||||||
|
|
@ -77,10 +93,8 @@ class WebxdcService {
|
||||||
|
|
||||||
/// Gets the bundle an instance runs onto disk, verified.
|
/// Gets the bundle an instance runs onto disk, verified.
|
||||||
///
|
///
|
||||||
/// Rust checks the store for a newer version first and moves the instance to
|
/// Opens cached code without a network update check. Only a bundle that
|
||||||
/// it if there is one, so an app updates between two runs and never during
|
/// has not been downloaded yet needs the server.
|
||||||
/// one. Called when the user starts an app and never on message arrival: a
|
|
||||||
/// message must not be able to make a device fetch anything.
|
|
||||||
static Future<String?> prepareBundle(String instanceId) async {
|
static Future<String?> prepareBundle(String instanceId) async {
|
||||||
try {
|
try {
|
||||||
return await rust_webxdc.prepareBundle(instanceId: instanceId);
|
return await rust_webxdc.prepareBundle(instanceId: instanceId);
|
||||||
|
|
@ -90,6 +104,20 @@ class WebxdcService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final Set<String> _updatingInstances = {};
|
||||||
|
|
||||||
|
/// Best effort after closing. A failed check leaves the existing code usable.
|
||||||
|
static Future<void> cacheUpdate(String instanceId) async {
|
||||||
|
if (!_updatingInstances.add(instanceId)) return;
|
||||||
|
try {
|
||||||
|
await rust_webxdc.cacheUpdate(instanceId: instanceId);
|
||||||
|
} catch (error) {
|
||||||
|
Log.warn('checking for a webxdc update after closing failed: $error');
|
||||||
|
} finally {
|
||||||
|
_updatingInstances.remove(instanceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Future<rust_webxdc.WebxdcInstanceInfo?> instance(
|
static Future<rust_webxdc.WebxdcInstanceInfo?> instance(
|
||||||
String instanceId,
|
String instanceId,
|
||||||
) async {
|
) async {
|
||||||
|
|
@ -126,6 +154,7 @@ class WebxdcService {
|
||||||
String? href,
|
String? href,
|
||||||
String? summary,
|
String? summary,
|
||||||
String? document,
|
String? document,
|
||||||
|
String? notify,
|
||||||
}) => rust_webxdc.sendUpdate(
|
}) => rust_webxdc.sendUpdate(
|
||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
|
|
@ -133,6 +162,7 @@ class WebxdcService {
|
||||||
href: href,
|
href: href,
|
||||||
summary: summary,
|
summary: summary,
|
||||||
document: document,
|
document: document,
|
||||||
|
notify: notify,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Removes an instance, its whole update log, and the web storage its origin
|
/// Removes an instance, its whole update log, and the web storage its origin
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,7 @@ class WebxdcHost {
|
||||||
/// Gets an app ready to run: makes sure the bundle is on disk and verified,
|
/// Gets an app ready to run: makes sure the bundle is on disk and verified,
|
||||||
/// and returns what the view needs to show it.
|
/// and returns what the view needs to show it.
|
||||||
///
|
///
|
||||||
/// Rust checks the store for a newer version as part of this, so an app
|
/// Cached apps open without a network update check. Returns a failure when the bundle
|
||||||
/// updates here and nowhere else. Returns a failure instead when the bundle
|
|
||||||
/// cannot be had at all -- a first start with no network, or an app that was
|
/// cannot be had at all -- a first start with no network, or an app that was
|
||||||
/// taken out of the store before this device ever downloaded it.
|
/// taken out of the store before this device ever downloaded it.
|
||||||
/// `languages` is what the reader prefers, most preferred first: the title
|
/// `languages` is what the reader prefers, most preferred first: the title
|
||||||
|
|
@ -104,8 +103,7 @@ class WebxdcHost {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
return const WebxdcLaunch.failed('unavailable');
|
return const WebxdcLaunch.failed('unavailable');
|
||||||
}
|
}
|
||||||
// The only place a bundle is ever fetched. A message arriving in a chat
|
// A first launch may need a download. Existing bundles are read locally.
|
||||||
// never reaches this.
|
|
||||||
final bundlePath = await WebxdcService.prepareBundle(instanceId);
|
final bundlePath = await WebxdcService.prepareBundle(instanceId);
|
||||||
if (bundlePath == null) {
|
if (bundlePath == null) {
|
||||||
return const WebxdcLaunch.failed('unavailable');
|
return const WebxdcLaunch.failed('unavailable');
|
||||||
|
|
@ -148,6 +146,8 @@ class WebxdcHost {
|
||||||
_updateSubscription = null;
|
_updateSubscription = null;
|
||||||
_openInstanceId = null;
|
_openInstanceId = null;
|
||||||
_closeView = null;
|
_closeView = null;
|
||||||
|
// Closing never waits for the server; downloaded code is used next time.
|
||||||
|
unawaited(WebxdcService.cacheUpdate(instanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _clearOrigin(String origin) async {
|
static Future<void> _clearOrigin(String origin) async {
|
||||||
|
|
@ -222,6 +222,10 @@ class WebxdcHost {
|
||||||
final params = (message['params'] as Map<String, dynamic>?) ?? {};
|
final params = (message['params'] as Map<String, dynamic>?) ?? {};
|
||||||
try {
|
try {
|
||||||
switch (message['method']) {
|
switch (message['method']) {
|
||||||
|
case 'getMembers':
|
||||||
|
final members = await rust_webxdc.members(instanceId: instanceId);
|
||||||
|
return jsonEncode({'id': id, 'result': jsonDecode(members)});
|
||||||
|
|
||||||
case 'sendUpdate':
|
case 'sendUpdate':
|
||||||
// `payload` is re-encoded rather than passed through, so what is
|
// `payload` is re-encoded rather than passed through, so what is
|
||||||
// stored and sent is JSON this side produced.
|
// stored and sent is JSON this side produced.
|
||||||
|
|
@ -232,6 +236,9 @@ class WebxdcHost {
|
||||||
href: params['href'] as String?,
|
href: params['href'] as String?,
|
||||||
summary: params['summary'] as String?,
|
summary: params['summary'] as String?,
|
||||||
document: params['document'] as String?,
|
document: params['document'] as String?,
|
||||||
|
notify: params['notify'] == null
|
||||||
|
? null
|
||||||
|
: jsonEncode(params['notify']),
|
||||||
);
|
);
|
||||||
return jsonEncode({'id': id, 'result': null});
|
return jsonEncode({'id': id, 'result': null});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,7 @@ class GroupContextMenu extends StatelessWidget {
|
||||||
),
|
),
|
||||||
ContextMenuItem(
|
ContextMenuItem(
|
||||||
title: context.lang.contextMenuOpenChat,
|
title: context.lang.contextMenuOpenChat,
|
||||||
onTap: () =>
|
onTap: () => navigator.context.push(
|
||||||
navigator.context.push(
|
|
||||||
Routes.chatsMessages(group.groupId),
|
Routes.chatsMessages(group.groupId),
|
||||||
extra: group,
|
extra: group,
|
||||||
),
|
),
|
||||||
|
|
@ -76,17 +75,6 @@ class GroupContextMenu extends StatelessWidget {
|
||||||
);
|
);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
await twonlyDB.messagesDao.deleteMessagesByGroupId(group.groupId);
|
await twonlyDB.messagesDao.deleteMessagesByGroupId(group.groupId);
|
||||||
if (group.isDirectChat) {
|
|
||||||
await twonlyDB.groupsDao.deleteGroup(group.groupId);
|
|
||||||
} else {
|
|
||||||
await twonlyDB.groupsDao.deleteGroup(group.groupId);
|
|
||||||
// await twonlyDB.groupsDao.updateGroup(
|
|
||||||
// group.groupId,
|
|
||||||
// const GroupsCompanion(
|
|
||||||
// deletedContent: Value(true),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
37
lib/src/visual/elements/pro_badge.element.dart
Normal file
37
lib/src/visual/elements/pro_badge.element.dart
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
|
class ProBadge extends StatelessWidget {
|
||||||
|
const ProBadge({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.amber.shade700,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const FaIcon(
|
||||||
|
FontAwesomeIcons.star,
|
||||||
|
size: 10,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
context.lang.backupCloudProBadge,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,17 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:twonly/core/bridge/webxdc.dart' as rust_webxdc;
|
import 'package:twonly/core/bridge/webxdc.dart' as rust_webxdc;
|
||||||
import 'package:twonly/locator.dart';
|
import 'package:twonly/locator.dart';
|
||||||
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/providers/purchases.provider.dart';
|
||||||
|
import 'package:twonly/src/services/subscription.service.dart';
|
||||||
import 'package:twonly/src/services/webxdc/webxdc.service.dart';
|
import 'package:twonly/src/services/webxdc/webxdc.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/visual/elements/pro_badge.element.dart';
|
||||||
|
|
||||||
/// The in-app store.
|
/// The in-app store.
|
||||||
///
|
///
|
||||||
|
|
@ -44,11 +50,13 @@ class _WebxdcStoreViewState extends State<WebxdcStoreView> {
|
||||||
// The cached listing is shown first so the sheet is never empty while the
|
// The cached listing is shown first so the sheet is never empty while the
|
||||||
// refresh is in flight.
|
// refresh is in flight.
|
||||||
final languages = [language];
|
final languages = [language];
|
||||||
final cached = await WebxdcService.catalog(languages);
|
final cached = await WebxdcService.catalog(widget.group.groupId, languages);
|
||||||
if (mounted) setState(() => _apps = cached);
|
if (mounted) setState(() => _apps = cached);
|
||||||
|
|
||||||
final refreshed = await WebxdcService.refreshCatalog();
|
final refreshed = await WebxdcService.refreshCatalog();
|
||||||
final apps = refreshed ? await WebxdcService.catalog(languages) : cached;
|
final apps = refreshed
|
||||||
|
? await WebxdcService.catalog(widget.group.groupId, languages)
|
||||||
|
: cached;
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_apps = apps;
|
_apps = apps;
|
||||||
|
|
@ -57,6 +65,10 @@ class _WebxdcStoreViewState extends State<WebxdcStoreView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _place(rust_webxdc.WebxdcStoreApp app) async {
|
Future<void> _place(rust_webxdc.WebxdcStoreApp app) async {
|
||||||
|
if (app.proOnly && !isPayingUser(context.read<PurchasesProvider>().plan)) {
|
||||||
|
await context.push(Routes.settingsSubscription);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setState(() => _placing = app.appId);
|
setState(() => _placing = app.appId);
|
||||||
final instanceId = await WebxdcService.createInstance(
|
final instanceId = await WebxdcService.createInstance(
|
||||||
widget.group.groupId,
|
widget.group.groupId,
|
||||||
|
|
@ -140,19 +152,45 @@ class _WebxdcStoreViewState extends State<WebxdcStoreView> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
final available = apps
|
||||||
|
.where((app) => !app.oneTime || app.instanceId == null)
|
||||||
|
.toList();
|
||||||
|
final alreadyAdded = apps
|
||||||
|
.where((app) => app.oneTime && app.instanceId != null)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return ListView(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
itemCount: apps.length,
|
children: [
|
||||||
itemBuilder: (context, index) {
|
...available.map(_appTile),
|
||||||
final app = apps[index];
|
if (alreadyAdded.isNotEmpty) ...[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 18, 20, 6),
|
||||||
|
child: Text(
|
||||||
|
context.lang.webxdcStoreAlreadyAdded,
|
||||||
|
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||||
|
color: context.color.onSurfaceVariant,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...alreadyAdded.map(
|
||||||
|
(app) =>
|
||||||
|
Opacity(opacity: 0.45, child: _appTile(app, disabled: true)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _appTile(
|
||||||
|
rust_webxdc.WebxdcStoreApp app, {
|
||||||
|
bool disabled = false,
|
||||||
|
}) {
|
||||||
final icon = app.icon;
|
final icon = app.icon;
|
||||||
// What the app says about itself, in the reader's language, as the
|
|
||||||
// store published it. Plain text, bounded and stripped of control
|
|
||||||
// characters before it was ever accepted for publishing.
|
|
||||||
final subtitle = userService.currentUser.isDeveloper
|
final subtitle = userService.currentUser.isDeveloper
|
||||||
? ['v${app.version}', ?app.description].join(' · ')
|
? ['v${app.version}', ?app.description].join(' · ')
|
||||||
: app.description;
|
: app.description;
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: SizedBox(
|
leading: SizedBox(
|
||||||
width: 40,
|
width: 40,
|
||||||
|
|
@ -174,10 +212,10 @@ class _WebxdcStoreViewState extends State<WebxdcStoreView> {
|
||||||
height: 20,
|
height: 20,
|
||||||
child: CircularProgressIndicator(strokeWidth: 2),
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
)
|
)
|
||||||
|
: app.proOnly
|
||||||
|
? const ProBadge()
|
||||||
: null,
|
: null,
|
||||||
onTap: _placing == null ? () => _place(app) : null,
|
onTap: !disabled && _placing == null ? () => _place(app) : null,
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import 'package:twonly/src/visual/views/contact/contact_components/user_discover
|
||||||
import 'package:twonly/src/visual/views/contact/contact_components/verification_expansion_tile.comp.dart';
|
import 'package:twonly/src/visual/views/contact/contact_components/verification_expansion_tile.comp.dart';
|
||||||
import 'package:twonly/src/visual/views/contact/select_contact_groups.view.dart';
|
import 'package:twonly/src/visual/views/contact/select_contact_groups.view.dart';
|
||||||
import 'package:twonly/src/visual/views/groups/group.view.dart';
|
import 'package:twonly/src/visual/views/groups/group.view.dart';
|
||||||
|
import 'package:twonly/src/visual/views/webxdc/webxdc_chat_apps.view.dart';
|
||||||
|
|
||||||
class ContactView extends StatefulWidget {
|
class ContactView extends StatefulWidget {
|
||||||
const ContactView(this.userId, {super.key});
|
const ContactView(this.userId, {super.key});
|
||||||
|
|
@ -233,6 +234,18 @@ class _ContactViewState extends State<ContactView> {
|
||||||
userService.currentUser.userId,
|
userService.currentUser.userId,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
BetterListTile(
|
||||||
|
icon: FontAwesomeIcons.layerGroup,
|
||||||
|
text: context.lang.webxdcChatAppsMenu,
|
||||||
|
onTap: () => context.navPush(
|
||||||
|
WebxdcChatAppsView(
|
||||||
|
groupId: getUUIDforDirectChat(
|
||||||
|
widget.userId,
|
||||||
|
userService.currentUser.userId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
ContactGroupsSubtitleBuilder(
|
ContactGroupsSubtitleBuilder(
|
||||||
userId: contact.userId,
|
userId: contact.userId,
|
||||||
builder: (context, subtitleWidget) {
|
builder: (context, subtitleWidget) {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import 'package:twonly/src/visual/views/contact/select_contact_groups.view.dart'
|
||||||
import 'package:twonly/src/visual/views/groups/group_create_select_members.view.dart';
|
import 'package:twonly/src/visual/views/groups/group_create_select_members.view.dart';
|
||||||
import 'package:twonly/src/visual/views/groups/group_member.context.dart';
|
import 'package:twonly/src/visual/views/groups/group_member.context.dart';
|
||||||
import 'package:twonly/src/visual/views/settings/profile/profile.view.dart';
|
import 'package:twonly/src/visual/views/settings/profile/profile.view.dart';
|
||||||
|
import 'package:twonly/src/visual/views/webxdc/webxdc_chat_apps.view.dart';
|
||||||
|
|
||||||
class GroupView extends StatefulWidget {
|
class GroupView extends StatefulWidget {
|
||||||
const GroupView(this.groupId, {super.key});
|
const GroupView(this.groupId, {super.key});
|
||||||
|
|
@ -213,6 +214,13 @@ class _GroupViewState extends State<GroupView> {
|
||||||
groupId: widget.groupId,
|
groupId: widget.groupId,
|
||||||
disabled: !_group!.isGroupAdmin,
|
disabled: !_group!.isGroupAdmin,
|
||||||
),
|
),
|
||||||
|
BetterListTile(
|
||||||
|
icon: FontAwesomeIcons.layerGroup,
|
||||||
|
text: context.lang.webxdcChatAppsMenu,
|
||||||
|
onTap: () => context.navPush(
|
||||||
|
WebxdcChatAppsView(groupId: widget.groupId),
|
||||||
|
),
|
||||||
|
),
|
||||||
ContactGroupsSubtitleBuilder(
|
ContactGroupsSubtitleBuilder(
|
||||||
groupId: widget.groupId,
|
groupId: widget.groupId,
|
||||||
builder: (context, subtitleWidget) {
|
builder: (context, subtitleWidget) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:twonly/locator.dart';
|
import 'package:twonly/locator.dart';
|
||||||
|
|
@ -12,6 +11,7 @@ import 'package:twonly/src/services/subscription.service.dart';
|
||||||
import 'package:twonly/src/services/user.service.dart';
|
import 'package:twonly/src/services/user.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/visual/elements/my_button.element.dart';
|
import 'package:twonly/src/visual/elements/my_button.element.dart';
|
||||||
|
import 'package:twonly/src/visual/elements/pro_badge.element.dart';
|
||||||
|
|
||||||
class MemoriesCloudBackupPromoComp extends StatelessWidget {
|
class MemoriesCloudBackupPromoComp extends StatelessWidget {
|
||||||
const MemoriesCloudBackupPromoComp({super.key});
|
const MemoriesCloudBackupPromoComp({super.key});
|
||||||
|
|
@ -75,35 +75,7 @@ class MemoriesCloudBackupPromoComp extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Container(
|
const ProBadge(),
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 6,
|
|
||||||
vertical: 2,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.amber.shade700,
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const FaIcon(
|
|
||||||
FontAwesomeIcons.star,
|
|
||||||
size: 10,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
context.lang.backupCloudProBadge,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 10,
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import 'package:twonly/src/services/user.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/visual/elements/better_list_title.element.dart';
|
import 'package:twonly/src/visual/elements/better_list_title.element.dart';
|
||||||
import 'package:twonly/src/visual/elements/my_button.element.dart';
|
import 'package:twonly/src/visual/elements/my_button.element.dart';
|
||||||
|
import 'package:twonly/src/visual/elements/pro_badge.element.dart';
|
||||||
import 'package:twonly/src/visual/themes/light.dart';
|
import 'package:twonly/src/visual/themes/light.dart';
|
||||||
import 'package:twonly/src/visual/views/settings/backup/backup_utils.dart';
|
import 'package:twonly/src/visual/views/settings/backup/backup_utils.dart';
|
||||||
import 'package:twonly/src/visual/views/settings/backup/components/recovery_card.comp.dart';
|
import 'package:twonly/src/visual/views/settings/backup/components/recovery_card.comp.dart';
|
||||||
|
|
@ -206,39 +207,12 @@ class _BackupViewState extends State<BackupView> {
|
||||||
: '-')),
|
: '-')),
|
||||||
),
|
),
|
||||||
trailing: isFreePlan
|
trailing: isFreePlan
|
||||||
? Row(
|
? const Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
ProBadge(),
|
||||||
padding: const EdgeInsets.symmetric(
|
SizedBox(width: 8),
|
||||||
horizontal: 6,
|
Switch(
|
||||||
vertical: 2,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.amber.shade700,
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const FaIcon(
|
|
||||||
FontAwesomeIcons.star,
|
|
||||||
size: 10,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
context.lang.backupCloudProBadge,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 10,
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
const Switch(
|
|
||||||
value: false,
|
value: false,
|
||||||
onChanged: null,
|
onChanged: null,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ class _PlanCardState extends State<PlanCard> {
|
||||||
context.lang.proFeature2,
|
context.lang.proFeature2,
|
||||||
context.lang.proFeature3,
|
context.lang.proFeature3,
|
||||||
context.lang.proFeature4,
|
context.lang.proFeature4,
|
||||||
// context.lang.proFeature4,
|
context.lang.subscriptionAllApps,
|
||||||
];
|
];
|
||||||
case 'Family':
|
case 'Family':
|
||||||
features = [
|
features = [
|
||||||
|
|
@ -384,6 +384,7 @@ class _PlanCardState extends State<PlanCard> {
|
||||||
context.lang.familyFeature2,
|
context.lang.familyFeature2,
|
||||||
context.lang.familyFeature3,
|
context.lang.familyFeature3,
|
||||||
context.lang.familyFeature4,
|
context.lang.familyFeature4,
|
||||||
|
context.lang.subscriptionAllApps,
|
||||||
];
|
];
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
lib/src/visual/views/webxdc/webxdc_chat_apps.view.dart
Normal file
112
lib/src/visual/views/webxdc/webxdc_chat_apps.view.dart
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:twonly/core/bridge/webxdc.dart' as rust_webxdc;
|
||||||
|
import 'package:twonly/src/services/webxdc/webxdc.service.dart';
|
||||||
|
import 'package:twonly/src/services/webxdc/webxdc_host.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/visual/views/chats/chat_messages_components/entries/common.dart';
|
||||||
|
import 'package:twonly/src/visual/views/webxdc/webxdc_app.view.dart';
|
||||||
|
|
||||||
|
/// One-time apps already attached to a chat, kept close to its profile.
|
||||||
|
class WebxdcChatAppsView extends StatefulWidget {
|
||||||
|
const WebxdcChatAppsView({required this.groupId, super.key});
|
||||||
|
|
||||||
|
final String groupId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WebxdcChatAppsView> createState() => _WebxdcChatAppsViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WebxdcChatAppsViewState extends State<WebxdcChatAppsView> {
|
||||||
|
List<rust_webxdc.WebxdcOneTimeInstance>? _apps;
|
||||||
|
bool _loading = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
if (_loading) return;
|
||||||
|
_loading = true;
|
||||||
|
_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _load() async {
|
||||||
|
final apps = await WebxdcService.oneTimeInstances(
|
||||||
|
widget.groupId,
|
||||||
|
readerLanguages(context),
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_apps = apps;
|
||||||
|
_loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _open(rust_webxdc.WebxdcOneTimeInstance app) async {
|
||||||
|
final messenger = ScaffoldMessenger.of(context);
|
||||||
|
final unavailable = context.lang.webxdcUnavailable;
|
||||||
|
final launch = await WebxdcHost.prepare(
|
||||||
|
app.instanceId,
|
||||||
|
readerLanguages(context),
|
||||||
|
);
|
||||||
|
if (launch.failure != null) {
|
||||||
|
messenger.showSnackBar(SnackBar(content: Text(unavailable)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mounted) return;
|
||||||
|
await context.navPush(WebxdcAppView(launch: launch));
|
||||||
|
await _load();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final apps = _apps;
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: Text(context.lang.webxdcChatAppsTitle)),
|
||||||
|
body: apps == null
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: apps.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Text(
|
||||||
|
context.lang.webxdcChatAppsEmpty,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ListView.builder(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
itemCount: apps.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final app = apps[index];
|
||||||
|
final subtitle = app.document ?? app.summary;
|
||||||
|
return ListTile(
|
||||||
|
leading: SizedBox(
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
child: app.icon == null
|
||||||
|
? const Center(
|
||||||
|
child: FaIcon(FontAwesomeIcons.puzzlePiece),
|
||||||
|
)
|
||||||
|
: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(9),
|
||||||
|
child: Image.memory(app.icon!, fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(app.name),
|
||||||
|
subtitle: subtitle == null
|
||||||
|
? null
|
||||||
|
: Text(
|
||||||
|
subtitle,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
trailing: const Icon(Icons.chevron_right),
|
||||||
|
onTap: () => _open(app),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "SELECT app_id AS \"app_id!: String\", version AS \"version!: i64\",\n name AS \"name!: String\",\n name_translations AS \"name_translations!: String\",\n source_code_url AS \"source_code_url: String\",\n description AS \"description!: String\",\n icon AS \"icon: Vec<u8>\", bundle_bytes AS \"bundle_bytes!: i64\"\n FROM webxdc_apps\n WHERE published = 1\n AND version = (SELECT MAX(version) FROM webxdc_apps AS newer\n WHERE newer.app_id = webxdc_apps.app_id AND newer.published = 1)\n ORDER BY name ASC",
|
"query": "SELECT app_id AS \"app_id!: String\", version AS \"version!: i64\",\n name AS \"name!: String\",\n pro_only AS \"pro_only!: bool\",\n one_time AS \"one_time!: bool\",\n (SELECT instance_id FROM webxdc_instances\n WHERE webxdc_instances.group_id = ?\n AND webxdc_instances.app_id = webxdc_apps.app_id\n ORDER BY created_at ASC LIMIT 1) AS \"instance_id: String\",\n name_translations AS \"name_translations!: String\",\n source_code_url AS \"source_code_url: String\",\n description AS \"description!: String\",\n icon AS \"icon: Vec<u8>\", bundle_bytes AS \"bundle_bytes!: i64\"\n FROM webxdc_apps\n WHERE published = 1\n AND version = (SELECT MAX(version) FROM webxdc_apps AS newer\n WHERE newer.app_id = webxdc_apps.app_id AND newer.published = 1)\n ORDER BY sort_order ASC, name ASC, app_id ASC",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
|
@ -37,8 +37,41 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "name_translations!: String",
|
"name": "pro_only!: bool",
|
||||||
"ordinal": 3,
|
"ordinal": 3,
|
||||||
|
"type_info": "Bool",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_apps",
|
||||||
|
"name": "pro_only"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "one_time!: bool",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Bool",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_apps",
|
||||||
|
"name": "one_time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "instance_id: String",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_instances",
|
||||||
|
"name": "instance_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name_translations!: String",
|
||||||
|
"ordinal": 6,
|
||||||
"type_info": "Text",
|
"type_info": "Text",
|
||||||
"origin": {
|
"origin": {
|
||||||
"Table": {
|
"Table": {
|
||||||
|
|
@ -49,7 +82,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "source_code_url: String",
|
"name": "source_code_url: String",
|
||||||
"ordinal": 4,
|
"ordinal": 7,
|
||||||
"type_info": "Text",
|
"type_info": "Text",
|
||||||
"origin": {
|
"origin": {
|
||||||
"Table": {
|
"Table": {
|
||||||
|
|
@ -60,7 +93,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "description!: String",
|
"name": "description!: String",
|
||||||
"ordinal": 5,
|
"ordinal": 8,
|
||||||
"type_info": "Text",
|
"type_info": "Text",
|
||||||
"origin": {
|
"origin": {
|
||||||
"Table": {
|
"Table": {
|
||||||
|
|
@ -71,7 +104,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "icon: Vec<u8>",
|
"name": "icon: Vec<u8>",
|
||||||
"ordinal": 6,
|
"ordinal": 9,
|
||||||
"type_info": "Blob",
|
"type_info": "Blob",
|
||||||
"origin": {
|
"origin": {
|
||||||
"Table": {
|
"Table": {
|
||||||
|
|
@ -82,7 +115,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bundle_bytes!: i64",
|
"name": "bundle_bytes!: i64",
|
||||||
"ordinal": 7,
|
"ordinal": 10,
|
||||||
"type_info": "Integer",
|
"type_info": "Integer",
|
||||||
"origin": {
|
"origin": {
|
||||||
"Table": {
|
"Table": {
|
||||||
|
|
@ -93,18 +126,21 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Right": 0
|
"Right": 1
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "b71a58e0499f8b69debddba47cf1ec86c4b99309441a4506e998beedfcead834"
|
"hash": "1eb6b6e8e4ed43f43c3e6c570ffad96638f7c02d4baa4bdea006ea2a439ec24f"
|
||||||
}
|
}
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n UPDATE groups\n SET last_message_exchange = MAX(last_message_exchange, ?)\n WHERE group_id = ?\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 2
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "3d1fdb8baa14a261fd2e2943ce5712ed95f12e337e88c18619aed086ebbd42aa"
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE groups\n SET last_message_exchange = MAX(last_message_exchange, ?),\n deleted_content = 0\n WHERE group_id = ?\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 2
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "3e9671207184c4df6b3d3c96bf4201160e557039a18115c4aa1737a80ebb5153"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "SELECT instance.instance_id AS \"instance_id!: String\",\n app.name AS \"name!: String\",\n app.name_translations AS \"name_translations!: String\",\n app.icon AS \"icon: Vec<u8>\",\n instance.summary AS \"summary: String\",\n instance.document AS \"document: String\"\n FROM webxdc_instances AS instance\n JOIN webxdc_apps AS app\n ON app.app_id = instance.app_id AND app.version = instance.version\n WHERE instance.group_id = ? AND app.one_time = 1\n ORDER BY instance.last_update_at DESC, instance.created_at DESC",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "instance_id!: String",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Text",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_instances",
|
||||||
|
"name": "instance_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name!: String",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Text",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_apps",
|
||||||
|
"name": "name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name_translations!: String",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Text",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_apps",
|
||||||
|
"name": "name_translations"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon: Vec<u8>",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Blob",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_apps",
|
||||||
|
"name": "icon"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "summary: String",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_instances",
|
||||||
|
"name": "summary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "document: String",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text",
|
||||||
|
"origin": {
|
||||||
|
"Table": {
|
||||||
|
"table": "webxdc_instances",
|
||||||
|
"name": "document"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "7a89aa45a3186a9a4c712976e21d7a4e3c289b449bd5ce432845cbdc02b234a6"
|
||||||
|
}
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "INSERT INTO webxdc_apps\n (app_id, version, name, name_translations, source_code_url,\n description, icon, bundle_sha256, bundle_bytes, published,\n cached_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)\n ON CONFLICT(app_id, version) DO UPDATE SET\n name = excluded.name,\n name_translations = excluded.name_translations,\n source_code_url = excluded.source_code_url,\n description = excluded.description,\n icon = excluded.icon,\n bundle_sha256 = excluded.bundle_sha256,\n bundle_bytes = excluded.bundle_bytes,\n published = 1,\n cached_at = excluded.cached_at",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 10
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "cc6625aa285f9e6dcdc1a73d7bfb6ad23cff6c8932f61b48645c431dd7adaf48"
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "UPDATE groups SET last_message_exchange = CAST(strftime('%s','now') AS INTEGER), deleted_content = 0 WHERE group_id = ?",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 1
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "cdd3c7feb92de75c85642d5f99d0ac3f8bb715da50ba1fd25484041cd50a2818"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "INSERT INTO webxdc_apps\n (app_id, version, name, name_translations, source_code_url,\n description, icon, bundle_sha256, bundle_bytes, published,\n cached_at, pro_only, sort_order, one_time)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)\n ON CONFLICT(app_id, version) DO UPDATE SET\n name = excluded.name,\n name_translations = excluded.name_translations,\n source_code_url = excluded.source_code_url,\n description = excluded.description,\n icon = excluded.icon,\n bundle_sha256 = excluded.bundle_sha256,\n bundle_bytes = excluded.bundle_bytes,\n published = 1,\n pro_only = excluded.pro_only,\n sort_order = excluded.sort_order,\n one_time = excluded.one_time,\n cached_at = excluded.cached_at",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 13
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "fa52c200d8a2e33db876b41d77b460d0d697d3818061c59cf7c20106c1a64175"
|
||||||
|
}
|
||||||
|
|
@ -680,6 +680,7 @@ pub(crate) async fn handle_encrypted(
|
||||||
let notification_content = content.clone();
|
let notification_content = content.clone();
|
||||||
handle_encrypted_inner(ctx, t, from_user_id, receipt_id, content).await?;
|
handle_encrypted_inner(ctx, t, from_user_id, receipt_id, content).await?;
|
||||||
crate::services::notifications::record_incoming_event(
|
crate::services::notifications::record_incoming_event(
|
||||||
|
ctx,
|
||||||
t,
|
t,
|
||||||
from_user_id,
|
from_user_id,
|
||||||
receipt_id,
|
receipt_id,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use prost::Message as ProstMessage;
|
||||||
use sqlx::{Sqlite, Transaction};
|
use sqlx::{Sqlite, Transaction};
|
||||||
|
|
||||||
pub(crate) async fn handle_additional_data_message(
|
pub(crate) async fn handle_additional_data_message(
|
||||||
ctx: &Context,
|
ctx: &std::sync::Arc<Context>,
|
||||||
tr: &mut Transaction<'_, Sqlite>,
|
tr: &mut Transaction<'_, Sqlite>,
|
||||||
from_user_id: i64,
|
from_user_id: i64,
|
||||||
group_id: &str,
|
group_id: &str,
|
||||||
|
|
@ -40,7 +40,20 @@ pub(crate) async fn handle_additional_data_message(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(data) = data.as_ref() {
|
if let Some(data) = data.as_ref() {
|
||||||
if let Some(update) = data.webxdc_update.as_ref() {
|
if data.webxdc_sync_request.is_some() {
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
let group_id = group_id.to_owned();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(error) = WebxdcService::new(&ctx)
|
||||||
|
.send_one_time_apps_to_contact(&group_id, from_user_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
tracing::warn!(%error, "could not answer one-time app sync request");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if let Some(sync) = data.webxdc_sync.as_ref() {
|
||||||
|
WebxdcService::handle_sync_chunk(tr, group_id, from_user_id, sync).await?;
|
||||||
|
} else if let Some(update) = data.webxdc_update.as_ref() {
|
||||||
// App state belongs in the instance's own log, which is ordered,
|
// App state belongs in the instance's own log, which is ordered,
|
||||||
// gap free, and outside the reach of the chat's deletion timer.
|
// gap free, and outside the reach of the chat's deletion timer.
|
||||||
WebxdcService::handle_incoming_update(
|
WebxdcService::handle_incoming_update(
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,11 @@ pub(crate) async fn handle_group_create(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
GroupService::spawn_state_refresh_and_announce(ctx, group_id.to_owned());
|
GroupService::spawn_state_refresh_and_announce(ctx, group_id.to_owned());
|
||||||
|
crate::services::webxdc::WebxdcService::spawn_sync_request(
|
||||||
|
ctx,
|
||||||
|
group_id.to_owned(),
|
||||||
|
from_user_id,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,8 +133,13 @@ message WebxdcCatalogEntry {
|
||||||
// The name in every language the bundle carries it in, keyed the same way.
|
// The name in every language the bundle carries it in, keyed the same way.
|
||||||
// `name` is what a client shows when none of them is a language it reads.
|
// `name` is what a client shows when none of them is a language it reads.
|
||||||
map<string, string> name_translations = 10;
|
map<string, string> name_translations = 10;
|
||||||
|
bool pro_only = 11;
|
||||||
|
// Only one instance of this app may be placed into a chat.
|
||||||
|
bool one_time = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
message WebxdcCatalog {
|
message WebxdcCatalog {
|
||||||
|
// Admin-defined app order, with versions of each app grouped newest first.
|
||||||
|
// Clients retain this order when caching and displaying the drawer.
|
||||||
repeated WebxdcCatalogEntry entries = 1;
|
repeated WebxdcCatalogEntry entries = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ message AdditionalMessageData {
|
||||||
WEBXDC_APP = 4;
|
WEBXDC_APP = 4;
|
||||||
WEBXDC_UPDATE = 5;
|
WEBXDC_UPDATE = 5;
|
||||||
WEBXDC_SENT = 6;
|
WEBXDC_SENT = 6;
|
||||||
|
WEBXDC_SYNC = 7;
|
||||||
|
WEBXDC_SYNC_REQUEST = 8;
|
||||||
}
|
}
|
||||||
Type type = 1;
|
Type type = 1;
|
||||||
|
|
||||||
|
|
@ -25,6 +27,45 @@ message AdditionalMessageData {
|
||||||
optional WebxdcApp webxdc_app = 6;
|
optional WebxdcApp webxdc_app = 6;
|
||||||
optional WebxdcUpdate webxdc_update = 7;
|
optional WebxdcUpdate webxdc_update = 7;
|
||||||
optional WebxdcOrigin webxdc_origin = 8;
|
optional WebxdcOrigin webxdc_origin = 8;
|
||||||
|
optional WebxdcSyncChunk webxdc_sync = 9;
|
||||||
|
optional WebxdcSyncRequest webxdc_sync_request = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A peer-to-peer transfer of existing one-time app state. The encoded payload
|
||||||
|
// is split into bounded hidden messages and installed only after every chunk
|
||||||
|
// arrived and the digest matches.
|
||||||
|
message WebxdcSyncChunk {
|
||||||
|
string transfer_id = 1;
|
||||||
|
uint32 chunk_index = 2;
|
||||||
|
uint32 chunk_count = 3;
|
||||||
|
bytes payload_sha256 = 4;
|
||||||
|
bytes payload = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WebxdcSyncRequest {}
|
||||||
|
|
||||||
|
message WebxdcSyncPayload {
|
||||||
|
repeated WebxdcSyncInstance instances = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WebxdcSyncInstance {
|
||||||
|
string instance_id = 1;
|
||||||
|
string app_id = 2;
|
||||||
|
int64 version = 3;
|
||||||
|
optional string summary = 4;
|
||||||
|
optional string document = 5;
|
||||||
|
int64 created_at = 6;
|
||||||
|
int64 last_update_at = 7;
|
||||||
|
repeated WebxdcSyncUpdate updates = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WebxdcSyncUpdate {
|
||||||
|
string message_id = 1;
|
||||||
|
optional int64 sender_id = 2;
|
||||||
|
string payload = 3;
|
||||||
|
optional string info = 4;
|
||||||
|
optional string href = 5;
|
||||||
|
int64 received_at = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attached to a message a webxdc app asked the user to send, so the chat can
|
// Attached to a message a webxdc app asked the user to send, so the chat can
|
||||||
|
|
@ -57,4 +98,7 @@ message WebxdcUpdate {
|
||||||
optional string href = 4;
|
optional string href = 4;
|
||||||
optional string summary = 5;
|
optional string summary = 5;
|
||||||
optional string document = 6;
|
optional string document = 6;
|
||||||
|
// JSON map of app-scoped member addresses to notification text.
|
||||||
|
// Absent preserves legacy broadcast; an empty map notifies nobody.
|
||||||
|
optional string notify = 7;
|
||||||
}
|
}
|
||||||
|
|
@ -126,9 +126,9 @@ impl Server {
|
||||||
ResponseOk::PasswordlessNotificationMessages(msgs) => Some(msgs),
|
ResponseOk::PasswordlessNotificationMessages(msgs) => Some(msgs),
|
||||||
// The server answers with `None` whenever the poll finds no unseen
|
// The server answers with `None` whenever the poll finds no unseen
|
||||||
// message, which is the normal outcome once every share arrived.
|
// message, which is the normal outcome once every share arrived.
|
||||||
ResponseOk::None(_) => Some(
|
ResponseOk::None(_) => {
|
||||||
proto::server_to_client::response::PasswordlessNotificationMessages::default(),
|
Some(proto::server_to_client::response::PasswordlessNotificationMessages::default())
|
||||||
),
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,18 @@ pub struct WebxdcStoreApp {
|
||||||
pub source_code_url: Option<String>,
|
pub source_code_url: Option<String>,
|
||||||
pub icon: Option<Vec<u8>>,
|
pub icon: Option<Vec<u8>>,
|
||||||
pub bundle_bytes: i64,
|
pub bundle_bytes: i64,
|
||||||
|
pub pro_only: bool,
|
||||||
|
pub one_time: bool,
|
||||||
|
/// The existing instance in this chat when a one-time app was already placed.
|
||||||
|
pub instance_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WebxdcOneTimeInstance {
|
||||||
|
pub instance_id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub icon: Option<Vec<u8>>,
|
||||||
|
pub summary: Option<String>,
|
||||||
|
pub document: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WebxdcInstanceInfo {
|
pub struct WebxdcInstanceInfo {
|
||||||
|
|
@ -66,12 +78,18 @@ pub async fn refresh_catalog() -> Result<()> {
|
||||||
/// `languages` is what the UI prefers, most preferred first. Names and
|
/// `languages` is what the UI prefers, most preferred first. Names and
|
||||||
/// descriptions are cached in every language the catalog carries and picked
|
/// descriptions are cached in every language the catalog carries and picked
|
||||||
/// here, so which language a user reads is never sent anywhere.
|
/// here, so which language a user reads is never sent anywhere.
|
||||||
pub async fn catalog(languages: Vec<String>) -> Result<Vec<WebxdcStoreApp>> {
|
pub async fn catalog(group_id: String, languages: Vec<String>) -> Result<Vec<WebxdcStoreApp>> {
|
||||||
let ctx = crate::context::Context::get_static()?;
|
let ctx = crate::context::Context::get_static()?;
|
||||||
let database = ctx.app_db.read().await.clone();
|
let database = ctx.app_db.read().await.clone();
|
||||||
let rows = sqlx::query!(
|
let rows = sqlx::query!(
|
||||||
r#"SELECT app_id AS "app_id!: String", version AS "version!: i64",
|
r#"SELECT app_id AS "app_id!: String", version AS "version!: i64",
|
||||||
name AS "name!: String",
|
name AS "name!: String",
|
||||||
|
pro_only AS "pro_only!: bool",
|
||||||
|
one_time AS "one_time!: bool",
|
||||||
|
(SELECT instance_id FROM webxdc_instances
|
||||||
|
WHERE webxdc_instances.group_id = ?
|
||||||
|
AND webxdc_instances.app_id = webxdc_apps.app_id
|
||||||
|
ORDER BY created_at ASC LIMIT 1) AS "instance_id: String",
|
||||||
name_translations AS "name_translations!: String",
|
name_translations AS "name_translations!: String",
|
||||||
source_code_url AS "source_code_url: String",
|
source_code_url AS "source_code_url: String",
|
||||||
description AS "description!: String",
|
description AS "description!: String",
|
||||||
|
|
@ -80,11 +98,12 @@ pub async fn catalog(languages: Vec<String>) -> Result<Vec<WebxdcStoreApp>> {
|
||||||
WHERE published = 1
|
WHERE published = 1
|
||||||
AND version = (SELECT MAX(version) FROM webxdc_apps AS newer
|
AND version = (SELECT MAX(version) FROM webxdc_apps AS newer
|
||||||
WHERE newer.app_id = webxdc_apps.app_id AND newer.published = 1)
|
WHERE newer.app_id = webxdc_apps.app_id AND newer.published = 1)
|
||||||
ORDER BY name ASC"#
|
ORDER BY sort_order ASC, name ASC, app_id ASC"#,
|
||||||
|
group_id,
|
||||||
)
|
)
|
||||||
.fetch_all(&database.pool)
|
.fetch_all(&database.pool)
|
||||||
.await?;
|
.await?;
|
||||||
let mut apps: Vec<WebxdcStoreApp> = rows
|
let apps: Vec<WebxdcStoreApp> = rows
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|row| WebxdcStoreApp {
|
.map(|row| WebxdcStoreApp {
|
||||||
app_id: row.app_id,
|
app_id: row.app_id,
|
||||||
|
|
@ -103,14 +122,54 @@ pub async fn catalog(languages: Vec<String>) -> Result<Vec<WebxdcStoreApp>> {
|
||||||
source_code_url: row.source_code_url,
|
source_code_url: row.source_code_url,
|
||||||
icon: row.icon,
|
icon: row.icon,
|
||||||
bundle_bytes: row.bundle_bytes,
|
bundle_bytes: row.bundle_bytes,
|
||||||
|
pro_only: row.pro_only,
|
||||||
|
one_time: row.one_time,
|
||||||
|
instance_id: row.instance_id,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
// The query orders by the untranslated name, which is not the order the
|
// Keep the server order even when names are localized for the reader.
|
||||||
// list is read in once the names are the reader's.
|
|
||||||
apps.sort_by_key(|app| app.name.to_lowercase());
|
|
||||||
Ok(apps)
|
Ok(apps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// One-time apps already placed into a chat, for the profile shortcut.
|
||||||
|
pub async fn one_time_instances(
|
||||||
|
group_id: String,
|
||||||
|
languages: Vec<String>,
|
||||||
|
) -> Result<Vec<WebxdcOneTimeInstance>> {
|
||||||
|
let ctx = crate::context::Context::get_static()?;
|
||||||
|
let database = ctx.app_db.read().await.clone();
|
||||||
|
let rows = sqlx::query!(
|
||||||
|
r#"SELECT instance.instance_id AS "instance_id!: String",
|
||||||
|
app.name AS "name!: String",
|
||||||
|
app.name_translations AS "name_translations!: String",
|
||||||
|
app.icon AS "icon: Vec<u8>",
|
||||||
|
instance.summary AS "summary: String",
|
||||||
|
instance.document AS "document: String"
|
||||||
|
FROM webxdc_instances AS instance
|
||||||
|
JOIN webxdc_apps AS app
|
||||||
|
ON app.app_id = instance.app_id AND app.version = instance.version
|
||||||
|
WHERE instance.group_id = ? AND app.one_time = 1
|
||||||
|
ORDER BY instance.last_update_at DESC, instance.created_at DESC"#,
|
||||||
|
group_id,
|
||||||
|
)
|
||||||
|
.fetch_all(&database.pool)
|
||||||
|
.await?;
|
||||||
|
Ok(rows
|
||||||
|
.into_iter()
|
||||||
|
.map(|row| WebxdcOneTimeInstance {
|
||||||
|
instance_id: row.instance_id,
|
||||||
|
name: crate::services::webxdc::store::pick_localized(
|
||||||
|
&row.name_translations,
|
||||||
|
&languages,
|
||||||
|
)
|
||||||
|
.unwrap_or(row.name),
|
||||||
|
icon: row.icon,
|
||||||
|
summary: row.summary,
|
||||||
|
document: row.document,
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
/// Places an app into a chat and returns the id of the message that carries it.
|
/// Places an app into a chat and returns the id of the message that carries it.
|
||||||
pub async fn create_instance(group_id: String, app_id: String, version: i64) -> Result<String> {
|
pub async fn create_instance(group_id: String, app_id: String, version: i64) -> Result<String> {
|
||||||
let ctx = crate::context::Context::get_static()?;
|
let ctx = crate::context::Context::get_static()?;
|
||||||
|
|
@ -135,8 +194,8 @@ pub async fn instance(instance_id: String) -> Result<Option<WebxdcInstanceInfo>>
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Downloads and verifies the bundle if it is not already on disk, and returns
|
/// Opens cached code, adopting an update only if already downloaded.
|
||||||
/// where it landed. Called when the user starts an app, never on message
|
/// Downloads and verifies the pinned bundle only when it is missing. Called when the user starts an app, never on message
|
||||||
/// arrival: a message must not be able to make a device fetch anything.
|
/// arrival: a message must not be able to make a device fetch anything.
|
||||||
pub async fn prepare_bundle(instance_id: String) -> Result<String> {
|
pub async fn prepare_bundle(instance_id: String) -> Result<String> {
|
||||||
let ctx = crate::context::Context::get_static()?;
|
let ctx = crate::context::Context::get_static()?;
|
||||||
|
|
@ -144,6 +203,13 @@ pub async fn prepare_bundle(instance_id: String) -> Result<String> {
|
||||||
Ok(path.display().to_string())
|
Ok(path.display().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Background update check after a webxdc app closes. Downloads only; the
|
||||||
|
/// running version changes on a later prepare_bundle call, never mid-session.
|
||||||
|
pub async fn cache_update(instance_id: String) -> Result<()> {
|
||||||
|
let ctx = crate::context::Context::get_static()?;
|
||||||
|
WebxdcService::new(ctx).cache_update(&instance_id).await
|
||||||
|
}
|
||||||
|
|
||||||
/// Answers one request the webview made for a file inside the bundle.
|
/// Answers one request the webview made for a file inside the bundle.
|
||||||
///
|
///
|
||||||
/// The platform shim has already established that the request came from this
|
/// The platform shim has already established that the request came from this
|
||||||
|
|
@ -153,7 +219,7 @@ pub async fn serve(instance_id: String, request_path: String) -> Result<WebxdcRe
|
||||||
let service = WebxdcService::new(ctx);
|
let service = WebxdcService::new(ctx);
|
||||||
// The bundle the instance is pinned to, not whatever the store offers now:
|
// The bundle the instance is pinned to, not whatever the store offers now:
|
||||||
// every file of one run comes out of the same `.xdc`, and the store was
|
// every file of one run comes out of the same `.xdc`, and the store was
|
||||||
// already consulted when the app started.
|
// never changed by a background update check.
|
||||||
let path = service.pinned_bundle(&instance_id).await?;
|
let path = service.pinned_bundle(&instance_id).await?;
|
||||||
let init = service.init_script_values(&instance_id).await?;
|
let init = service.init_script_values(&instance_id).await?;
|
||||||
let response = bundle::serve(&path, &request_path, &init);
|
let response = bundle::serve(&path, &request_path, &init);
|
||||||
|
|
@ -190,10 +256,11 @@ pub async fn send_update(
|
||||||
href: Option<String>,
|
href: Option<String>,
|
||||||
summary: Option<String>,
|
summary: Option<String>,
|
||||||
document: Option<String>,
|
document: Option<String>,
|
||||||
|
notify: Option<String>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ctx = crate::context::Context::get_static()?;
|
let ctx = crate::context::Context::get_static()?;
|
||||||
WebxdcService::new(ctx)
|
WebxdcService::new(ctx)
|
||||||
.send_update(instance_id, payload, info, href, summary, document)
|
.send_update(instance_id, payload, info, href, summary, document, notify)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,3 +278,9 @@ pub async fn delete_instance(instance_id: String) -> Result<Option<String>> {
|
||||||
let ctx = crate::context::Context::get_static()?;
|
let ctx = crate::context::Context::get_static()?;
|
||||||
WebxdcService::new(ctx).delete_instance(&instance_id).await
|
WebxdcService::new(ctx).delete_instance(&instance_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Current members of the instance's chat; no account identifiers leave Rust.
|
||||||
|
pub async fn members(instance_id: String) -> Result<String> {
|
||||||
|
let ctx = crate::context::Context::get_static()?;
|
||||||
|
WebxdcService::new(ctx).members(&instance_id).await
|
||||||
|
}
|
||||||
|
|
|
||||||
1
rust/src/database/app/migrations/0019_webxdc_pro.sql
Normal file
1
rust/src/database/app/migrations/0019_webxdc_pro.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE webxdc_apps ADD COLUMN pro_only BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
2
rust/src/database/app/migrations/0020_webxdc_order.sql
Normal file
2
rust/src/database/app/migrations/0020_webxdc_order.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Retain the server catalog order when showing cached apps offline.
|
||||||
|
ALTER TABLE webxdc_apps ADD COLUMN sort_order INTEGER NOT NULL DEFAULT 0;
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Apps such as a shared expense ledger have one instance per chat.
|
||||||
|
ALTER TABLE webxdc_apps ADD COLUMN one_time BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
34
rust/src/database/app/migrations/0022_webxdc_sync.sql
Normal file
34
rust/src/database/app/migrations/0022_webxdc_sync.sql
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
-- Chunks survive process restarts and out-of-order delivery. They are removed
|
||||||
|
-- as soon as a complete, verified state transfer has been installed.
|
||||||
|
CREATE TABLE webxdc_sync_chunks (
|
||||||
|
transfer_id TEXT NOT NULL,
|
||||||
|
group_id TEXT NOT NULL REFERENCES groups(group_id) ON DELETE CASCADE,
|
||||||
|
sender_id INTEGER NOT NULL REFERENCES contacts(user_id) ON DELETE CASCADE,
|
||||||
|
chunk_index INTEGER NOT NULL,
|
||||||
|
chunk_count INTEGER NOT NULL,
|
||||||
|
payload_sha256 BLOB NOT NULL,
|
||||||
|
payload BLOB NOT NULL,
|
||||||
|
created_at INTEGER NOT NULL DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)),
|
||||||
|
PRIMARY KEY (transfer_id, sender_id, chunk_index)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_webxdc_sync_chunks_created_at
|
||||||
|
ON webxdc_sync_chunks(created_at);
|
||||||
|
|
||||||
|
-- A newly joined member can receive a live update before the instance snapshot.
|
||||||
|
-- Keep it until the app card arrives instead of dropping shared state.
|
||||||
|
CREATE TABLE webxdc_pending_updates (
|
||||||
|
message_id TEXT NOT NULL PRIMARY KEY,
|
||||||
|
instance_id TEXT NOT NULL,
|
||||||
|
group_id TEXT NOT NULL REFERENCES groups(group_id) ON DELETE CASCADE,
|
||||||
|
sender_id INTEGER NOT NULL REFERENCES contacts(user_id) ON DELETE CASCADE,
|
||||||
|
payload TEXT NOT NULL,
|
||||||
|
info TEXT,
|
||||||
|
href TEXT,
|
||||||
|
summary TEXT,
|
||||||
|
document TEXT,
|
||||||
|
received_at INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_webxdc_pending_updates_instance
|
||||||
|
ON webxdc_pending_updates(instance_id, received_at);
|
||||||
|
|
@ -330,7 +330,8 @@ impl Group {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
UPDATE groups
|
UPDATE groups
|
||||||
SET last_message_exchange = MAX(last_message_exchange, ?)
|
SET last_message_exchange = MAX(last_message_exchange, ?),
|
||||||
|
deleted_content = 0
|
||||||
WHERE group_id = ?
|
WHERE group_id = ?
|
||||||
"#,
|
"#,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
||||||
default_rust_auto_opaque = RustAutoOpaqueMoi,
|
default_rust_auto_opaque = RustAutoOpaqueMoi,
|
||||||
);
|
);
|
||||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0";
|
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0";
|
||||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1362207365;
|
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1591152700;
|
||||||
|
|
||||||
// Section: executor
|
// Section: executor
|
||||||
|
|
||||||
|
|
@ -161,6 +161,43 @@ fn wire__crate__bridge__webxdc__address_for_impl(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
fn wire__crate__bridge__webxdc__cache_update_impl(
|
||||||
|
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||||
|
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||||
|
rust_vec_len_: i32,
|
||||||
|
data_len_: i32,
|
||||||
|
) {
|
||||||
|
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
|
||||||
|
flutter_rust_bridge::for_generated::TaskInfo {
|
||||||
|
debug_name: "cache_update",
|
||||||
|
port: Some(port_),
|
||||||
|
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||||
|
},
|
||||||
|
move || {
|
||||||
|
let message = unsafe {
|
||||||
|
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
|
||||||
|
ptr_,
|
||||||
|
rust_vec_len_,
|
||||||
|
data_len_,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut deserializer =
|
||||||
|
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||||
|
let api_instance_id = <String>::sse_decode(&mut deserializer);
|
||||||
|
deserializer.end();
|
||||||
|
move |context| async move {
|
||||||
|
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||||
|
(move || async move {
|
||||||
|
let output_ok =
|
||||||
|
crate::bridge::webxdc::cache_update(api_instance_id).await?;
|
||||||
|
Ok(output_ok)
|
||||||
|
})()
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
fn wire__crate__bridge__webxdc__catalog_impl(
|
fn wire__crate__bridge__webxdc__catalog_impl(
|
||||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||||
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||||
|
|
@ -183,12 +220,14 @@ fn wire__crate__bridge__webxdc__catalog_impl(
|
||||||
};
|
};
|
||||||
let mut deserializer =
|
let mut deserializer =
|
||||||
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||||
|
let api_group_id = <String>::sse_decode(&mut deserializer);
|
||||||
let api_languages = <Vec<String>>::sse_decode(&mut deserializer);
|
let api_languages = <Vec<String>>::sse_decode(&mut deserializer);
|
||||||
deserializer.end();
|
deserializer.end();
|
||||||
move |context| async move {
|
move |context| async move {
|
||||||
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||||
(move || async move {
|
(move || async move {
|
||||||
let output_ok = crate::bridge::webxdc::catalog(api_languages).await?;
|
let output_ok =
|
||||||
|
crate::bridge::webxdc::catalog(api_group_id, api_languages).await?;
|
||||||
Ok(output_ok)
|
Ok(output_ok)
|
||||||
})()
|
})()
|
||||||
.await,
|
.await,
|
||||||
|
|
@ -820,6 +859,81 @@ fn wire__crate__bridge__groups__manage_admin_state_impl(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
fn wire__crate__bridge__webxdc__members_impl(
|
||||||
|
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||||
|
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||||
|
rust_vec_len_: i32,
|
||||||
|
data_len_: i32,
|
||||||
|
) {
|
||||||
|
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
|
||||||
|
flutter_rust_bridge::for_generated::TaskInfo {
|
||||||
|
debug_name: "members",
|
||||||
|
port: Some(port_),
|
||||||
|
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||||
|
},
|
||||||
|
move || {
|
||||||
|
let message = unsafe {
|
||||||
|
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
|
||||||
|
ptr_,
|
||||||
|
rust_vec_len_,
|
||||||
|
data_len_,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut deserializer =
|
||||||
|
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||||
|
let api_instance_id = <String>::sse_decode(&mut deserializer);
|
||||||
|
deserializer.end();
|
||||||
|
move |context| async move {
|
||||||
|
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||||
|
(move || async move {
|
||||||
|
let output_ok = crate::bridge::webxdc::members(api_instance_id).await?;
|
||||||
|
Ok(output_ok)
|
||||||
|
})()
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn wire__crate__bridge__webxdc__one_time_instances_impl(
|
||||||
|
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||||
|
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||||
|
rust_vec_len_: i32,
|
||||||
|
data_len_: i32,
|
||||||
|
) {
|
||||||
|
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
|
||||||
|
flutter_rust_bridge::for_generated::TaskInfo {
|
||||||
|
debug_name: "one_time_instances",
|
||||||
|
port: Some(port_),
|
||||||
|
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||||
|
},
|
||||||
|
move || {
|
||||||
|
let message = unsafe {
|
||||||
|
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
|
||||||
|
ptr_,
|
||||||
|
rust_vec_len_,
|
||||||
|
data_len_,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut deserializer =
|
||||||
|
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
|
||||||
|
let api_group_id = <String>::sse_decode(&mut deserializer);
|
||||||
|
let api_languages = <Vec<String>>::sse_decode(&mut deserializer);
|
||||||
|
deserializer.end();
|
||||||
|
move |context| async move {
|
||||||
|
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||||
|
(move || async move {
|
||||||
|
let output_ok =
|
||||||
|
crate::bridge::webxdc::one_time_instances(api_group_id, api_languages)
|
||||||
|
.await?;
|
||||||
|
Ok(output_ok)
|
||||||
|
})()
|
||||||
|
.await,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
fn wire__crate__bridge__webxdc__prepare_bundle_impl(
|
fn wire__crate__bridge__webxdc__prepare_bundle_impl(
|
||||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||||
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
|
||||||
|
|
@ -5592,6 +5706,7 @@ fn wire__crate__bridge__webxdc__send_update_impl(
|
||||||
let api_href = <Option<String>>::sse_decode(&mut deserializer);
|
let api_href = <Option<String>>::sse_decode(&mut deserializer);
|
||||||
let api_summary = <Option<String>>::sse_decode(&mut deserializer);
|
let api_summary = <Option<String>>::sse_decode(&mut deserializer);
|
||||||
let api_document = <Option<String>>::sse_decode(&mut deserializer);
|
let api_document = <Option<String>>::sse_decode(&mut deserializer);
|
||||||
|
let api_notify = <Option<String>>::sse_decode(&mut deserializer);
|
||||||
deserializer.end();
|
deserializer.end();
|
||||||
move |context| async move {
|
move |context| async move {
|
||||||
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||||
|
|
@ -5603,6 +5718,7 @@ fn wire__crate__bridge__webxdc__send_update_impl(
|
||||||
api_href,
|
api_href,
|
||||||
api_summary,
|
api_summary,
|
||||||
api_document,
|
api_document,
|
||||||
|
api_notify,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(output_ok)
|
Ok(output_ok)
|
||||||
|
|
@ -6671,6 +6787,20 @@ impl SseDecode for Vec<crate::database::app::SqlValue> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SseDecode for Vec<crate::bridge::webxdc::WebxdcOneTimeInstance> {
|
||||||
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
|
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||||
|
let mut len_ = <i32>::sse_decode(deserializer);
|
||||||
|
let mut ans_ = Vec::with_capacity(len_ as usize);
|
||||||
|
for idx_ in 0..len_ {
|
||||||
|
ans_.push(<crate::bridge::webxdc::WebxdcOneTimeInstance>::sse_decode(
|
||||||
|
deserializer,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return ans_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SseDecode for Vec<crate::bridge::webxdc::WebxdcStoreApp> {
|
impl SseDecode for Vec<crate::bridge::webxdc::WebxdcStoreApp> {
|
||||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||||
|
|
@ -7330,6 +7460,24 @@ impl SseDecode for crate::bridge::webxdc::WebxdcInstanceInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SseDecode for crate::bridge::webxdc::WebxdcOneTimeInstance {
|
||||||
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
|
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||||
|
let mut var_instanceId = <String>::sse_decode(deserializer);
|
||||||
|
let mut var_name = <String>::sse_decode(deserializer);
|
||||||
|
let mut var_icon = <Option<Vec<u8>>>::sse_decode(deserializer);
|
||||||
|
let mut var_summary = <Option<String>>::sse_decode(deserializer);
|
||||||
|
let mut var_document = <Option<String>>::sse_decode(deserializer);
|
||||||
|
return crate::bridge::webxdc::WebxdcOneTimeInstance {
|
||||||
|
instance_id: var_instanceId,
|
||||||
|
name: var_name,
|
||||||
|
icon: var_icon,
|
||||||
|
summary: var_summary,
|
||||||
|
document: var_document,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SseDecode for crate::bridge::webxdc::WebxdcResponse {
|
impl SseDecode for crate::bridge::webxdc::WebxdcResponse {
|
||||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||||
|
|
@ -7358,6 +7506,9 @@ impl SseDecode for crate::bridge::webxdc::WebxdcStoreApp {
|
||||||
let mut var_sourceCodeUrl = <Option<String>>::sse_decode(deserializer);
|
let mut var_sourceCodeUrl = <Option<String>>::sse_decode(deserializer);
|
||||||
let mut var_icon = <Option<Vec<u8>>>::sse_decode(deserializer);
|
let mut var_icon = <Option<Vec<u8>>>::sse_decode(deserializer);
|
||||||
let mut var_bundleBytes = <i64>::sse_decode(deserializer);
|
let mut var_bundleBytes = <i64>::sse_decode(deserializer);
|
||||||
|
let mut var_proOnly = <bool>::sse_decode(deserializer);
|
||||||
|
let mut var_oneTime = <bool>::sse_decode(deserializer);
|
||||||
|
let mut var_instanceId = <Option<String>>::sse_decode(deserializer);
|
||||||
return crate::bridge::webxdc::WebxdcStoreApp {
|
return crate::bridge::webxdc::WebxdcStoreApp {
|
||||||
app_id: var_appId,
|
app_id: var_appId,
|
||||||
version: var_version,
|
version: var_version,
|
||||||
|
|
@ -7366,6 +7517,9 @@ impl SseDecode for crate::bridge::webxdc::WebxdcStoreApp {
|
||||||
source_code_url: var_sourceCodeUrl,
|
source_code_url: var_sourceCodeUrl,
|
||||||
icon: var_icon,
|
icon: var_icon,
|
||||||
bundle_bytes: var_bundleBytes,
|
bundle_bytes: var_bundleBytes,
|
||||||
|
pro_only: var_proOnly,
|
||||||
|
one_time: var_oneTime,
|
||||||
|
instance_id: var_instanceId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7400,163 +7554,166 @@ fn pde_ffi_dispatcher_primary_impl(
|
||||||
1 => wire__crate__bridge__groups__add_hidden_contact_impl(port, ptr, rust_vec_len, data_len),
|
1 => wire__crate__bridge__groups__add_hidden_contact_impl(port, ptr, rust_vec_len, data_len),
|
||||||
2 => wire__crate__bridge__groups__add_new_group_members_impl(port, ptr, rust_vec_len, data_len),
|
2 => wire__crate__bridge__groups__add_new_group_members_impl(port, ptr, rust_vec_len, data_len),
|
||||||
3 => wire__crate__bridge__webxdc__address_for_impl(port, ptr, rust_vec_len, data_len),
|
3 => wire__crate__bridge__webxdc__address_for_impl(port, ptr, rust_vec_len, data_len),
|
||||||
4 => wire__crate__bridge__webxdc__catalog_impl(port, ptr, rust_vec_len, data_len),
|
4 => wire__crate__bridge__webxdc__cache_update_impl(port, ptr, rust_vec_len, data_len),
|
||||||
5 => wire__crate__bridge__logging__clean_log_file_impl(port, ptr, rust_vec_len, data_len),
|
5 => wire__crate__bridge__webxdc__catalog_impl(port, ptr, rust_vec_len, data_len),
|
||||||
6 => wire__crate__bridge__logging__clear_log_file_impl(port, ptr, rust_vec_len, data_len),
|
6 => wire__crate__bridge__logging__clean_log_file_impl(port, ptr, rust_vec_len, data_len),
|
||||||
7 => wire__crate__bridge__webxdc__create_instance_impl(port, ptr, rust_vec_len, data_len),
|
7 => wire__crate__bridge__logging__clear_log_file_impl(port, ptr, rust_vec_len, data_len),
|
||||||
8 => wire__crate__bridge__groups__create_new_group_impl(port, ptr, rust_vec_len, data_len),
|
8 => wire__crate__bridge__webxdc__create_instance_impl(port, ptr, rust_vec_len, data_len),
|
||||||
9 => wire__crate__bridge__webxdc__delete_instance_impl(port, ptr, rust_vec_len, data_len),
|
9 => wire__crate__bridge__groups__create_new_group_impl(port, ptr, rust_vec_len, data_len),
|
||||||
10 => wire__crate__bridge__groups__fetch_group_state_impl(port, ptr, rust_vec_len, data_len),
|
10 => wire__crate__bridge__webxdc__delete_instance_impl(port, ptr, rust_vec_len, data_len),
|
||||||
11 => wire__crate__bridge__groups__fetch_group_states_for_unjoined_groups_impl(port, ptr, rust_vec_len, data_len),
|
11 => wire__crate__bridge__groups__fetch_group_state_impl(port, ptr, rust_vec_len, data_len),
|
||||||
12 => wire__crate__bridge__groups__fetch_missing_group_public_keys_impl(port, ptr, rust_vec_len, data_len),
|
12 => wire__crate__bridge__groups__fetch_group_states_for_unjoined_groups_impl(port, ptr, rust_vec_len, data_len),
|
||||||
13 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_change_exclusion_for_contact_impl(port, ptr, rust_vec_len, data_len),
|
13 => wire__crate__bridge__groups__fetch_missing_group_public_keys_impl(port, ptr, rust_vec_len, data_len),
|
||||||
14 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(port, ptr, rust_vec_len, data_len),
|
14 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_change_exclusion_for_contact_impl(port, ptr, rust_vec_len, data_len),
|
||||||
15 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_update_verification_state_for_user_impl(port, ptr, rust_vec_len, data_len),
|
15 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_get_current_version_impl(port, ptr, rust_vec_len, data_len),
|
||||||
16 => wire__crate__bridge__callbacks__init_flutter_callbacks_impl(port, ptr, rust_vec_len, data_len),
|
16 => wire__crate__bridge__wrapper__user_discovery__flutter_user_discovery_update_verification_state_for_user_impl(port, ptr, rust_vec_len, data_len),
|
||||||
17 => wire__crate__bridge__initialize_twonly_flutter_impl(port, ptr, rust_vec_len, data_len),
|
17 => wire__crate__bridge__callbacks__init_flutter_callbacks_impl(port, ptr, rust_vec_len, data_len),
|
||||||
18 => wire__crate__bridge__initialize_twonly_standalone_impl(port, ptr, rust_vec_len, data_len),
|
18 => wire__crate__bridge__initialize_twonly_flutter_impl(port, ptr, rust_vec_len, data_len),
|
||||||
19 => wire__crate__bridge__webxdc__instance_impl(port, ptr, rust_vec_len, data_len),
|
19 => wire__crate__bridge__initialize_twonly_standalone_impl(port, ptr, rust_vec_len, data_len),
|
||||||
20 => wire__crate__bridge__groups__leave_group_impl(port, ptr, rust_vec_len, data_len),
|
20 => wire__crate__bridge__webxdc__instance_impl(port, ptr, rust_vec_len, data_len),
|
||||||
21 => wire__crate__bridge__logging__load_log_file_impl(port, ptr, rust_vec_len, data_len),
|
21 => wire__crate__bridge__groups__leave_group_impl(port, ptr, rust_vec_len, data_len),
|
||||||
22 => wire__crate__bridge__groups__manage_admin_state_impl(port, ptr, rust_vec_len, data_len),
|
22 => wire__crate__bridge__logging__load_log_file_impl(port, ptr, rust_vec_len, data_len),
|
||||||
23 => wire__crate__bridge__webxdc__prepare_bundle_impl(port, ptr, rust_vec_len, data_len),
|
23 => wire__crate__bridge__groups__manage_admin_state_impl(port, ptr, rust_vec_len, data_len),
|
||||||
24 => wire__crate__bridge__logging__read_last_log_lines_impl(port, ptr, rust_vec_len, data_len),
|
24 => wire__crate__bridge__webxdc__members_impl(port, ptr, rust_vec_len, data_len),
|
||||||
25 => wire__crate__bridge__webxdc__refresh_catalog_impl(port, ptr, rust_vec_len, data_len),
|
25 => wire__crate__bridge__webxdc__one_time_instances_impl(port, ptr, rust_vec_len, data_len),
|
||||||
26 => wire__crate__bridge__groups__remove_member_from_group_impl(port, ptr, rust_vec_len, data_len),
|
26 => wire__crate__bridge__webxdc__prepare_bundle_impl(port, ptr, rust_vec_len, data_len),
|
||||||
27 => wire__crate__bridge__api__rust_api_abandon_media_impl(port, ptr, rust_vec_len, data_len),
|
27 => wire__crate__bridge__logging__read_last_log_lines_impl(port, ptr, rust_vec_len, data_len),
|
||||||
28 => wire__crate__bridge__api__rust_api_add_additional_user_impl(port, ptr, rust_vec_len, data_len),
|
28 => wire__crate__bridge__webxdc__refresh_catalog_impl(port, ptr, rust_vec_len, data_len),
|
||||||
29 => wire__crate__bridge__api__rust_api_allocate_sequence_impl(port, ptr, rust_vec_len, data_len),
|
29 => wire__crate__bridge__groups__remove_member_from_group_impl(port, ptr, rust_vec_len, data_len),
|
||||||
31 => wire__crate__bridge__api__rust_api_authentication_headers_impl(port, ptr, rust_vec_len, data_len),
|
30 => wire__crate__bridge__api__rust_api_abandon_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
33 => wire__crate__bridge__api__rust_api_change_username_impl(port, ptr, rust_vec_len, data_len),
|
31 => wire__crate__bridge__api__rust_api_add_additional_user_impl(port, ptr, rust_vec_len, data_len),
|
||||||
34 => wire__crate__bridge__api__rust_api_check_for_deleted_usernames_impl(port, ptr, rust_vec_len, data_len),
|
32 => wire__crate__bridge__api__rust_api_allocate_sequence_impl(port, ptr, rust_vec_len, data_len),
|
||||||
35 => wire__crate__bridge__api__rust_api_check_for_passwordless_notification_impl(port, ptr, rust_vec_len, data_len),
|
34 => wire__crate__bridge__api__rust_api_authentication_headers_impl(port, ptr, rust_vec_len, data_len),
|
||||||
36 => wire__crate__bridge__api__rust_api_clear_contact_request_notifications_impl(port, ptr, rust_vec_len, data_len),
|
36 => wire__crate__bridge__api__rust_api_change_username_impl(port, ptr, rust_vec_len, data_len),
|
||||||
37 => wire__crate__bridge__api__rust_api_clear_conversation_notifications_impl(port, ptr, rust_vec_len, data_len),
|
37 => wire__crate__bridge__api__rust_api_check_for_deleted_usernames_impl(port, ptr, rust_vec_len, data_len),
|
||||||
38 => wire__crate__bridge__api__rust_api_close_impl(port, ptr, rust_vec_len, data_len),
|
38 => wire__crate__bridge__api__rust_api_check_for_passwordless_notification_impl(port, ptr, rust_vec_len, data_len),
|
||||||
39 => wire__crate__bridge__api__rust_api_confirm_memories_upload_impl(port, ptr, rust_vec_len, data_len),
|
39 => wire__crate__bridge__api__rust_api_clear_contact_request_notifications_impl(port, ptr, rust_vec_len, data_len),
|
||||||
40 => wire__crate__bridge__api__rust_api_connect_impl(port, ptr, rust_vec_len, data_len),
|
40 => wire__crate__bridge__api__rust_api_clear_conversation_notifications_impl(port, ptr, rust_vec_len, data_len),
|
||||||
41 => wire__crate__bridge__api__rust_api_connection_state_impl(port, ptr, rust_vec_len, data_len),
|
41 => wire__crate__bridge__api__rust_api_close_impl(port, ptr, rust_vec_len, data_len),
|
||||||
42 => wire__crate__bridge__api__rust_api_crop_media_transparent_borders_impl(port, ptr, rust_vec_len, data_len),
|
42 => wire__crate__bridge__api__rust_api_confirm_memories_upload_impl(port, ptr, rust_vec_len, data_len),
|
||||||
43 => wire__crate__bridge__api__rust_api_current_user_avatar_path_impl(port, ptr, rust_vec_len, data_len),
|
43 => wire__crate__bridge__api__rust_api_connect_impl(port, ptr, rust_vec_len, data_len),
|
||||||
45 => wire__crate__bridge__api__rust_api_delete_account_impl(port, ptr, rust_vec_len, data_len),
|
44 => wire__crate__bridge__api__rust_api_connection_state_impl(port, ptr, rust_vec_len, data_len),
|
||||||
46 => wire__crate__bridge__api__rust_api_delete_memory_impl(port, ptr, rust_vec_len, data_len),
|
45 => wire__crate__bridge__api__rust_api_crop_media_transparent_borders_impl(port, ptr, rust_vec_len, data_len),
|
||||||
47 => wire__crate__bridge__api__rust_api_delete_widget_media_impl(port, ptr, rust_vec_len, data_len),
|
46 => wire__crate__bridge__api__rust_api_current_user_avatar_path_impl(port, ptr, rust_vec_len, data_len),
|
||||||
48 => wire__crate__bridge__api__rust_api_disable_memories_backup_impl(port, ptr, rust_vec_len, data_len),
|
48 => wire__crate__bridge__api__rust_api_delete_account_impl(port, ptr, rust_vec_len, data_len),
|
||||||
49 => wire__crate__bridge__api__rust_api_download_done_impl(port, ptr, rust_vec_len, data_len),
|
49 => wire__crate__bridge__api__rust_api_delete_memory_impl(port, ptr, rust_vec_len, data_len),
|
||||||
50 => wire__crate__bridge__api__rust_api_download_media_impl(port, ptr, rust_vec_len, data_len),
|
50 => wire__crate__bridge__api__rust_api_delete_widget_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
51 => wire__crate__bridge__api__rust_api_download_pending_media_impl(port, ptr, rust_vec_len, data_len),
|
51 => wire__crate__bridge__api__rust_api_disable_memories_backup_impl(port, ptr, rust_vec_len, data_len),
|
||||||
52 => wire__crate__bridge__api__rust_api_ensure_avatar_png_impl(port, ptr, rust_vec_len, data_len),
|
52 => wire__crate__bridge__api__rust_api_download_done_impl(port, ptr, rust_vec_len, data_len),
|
||||||
53 => wire__crate__bridge__api__rust_api_establish_signal_session_impl(port, ptr, rust_vec_len, data_len),
|
53 => wire__crate__bridge__api__rust_api_download_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
54 => wire__crate__bridge__api__rust_api_events_impl(port, ptr, rust_vec_len, data_len),
|
54 => wire__crate__bridge__api__rust_api_download_pending_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
55 => wire__crate__bridge__api__rust_api_finish_started_media_uploads_impl(port, ptr, rust_vec_len, data_len),
|
55 => wire__crate__bridge__api__rust_api_ensure_avatar_png_impl(port, ptr, rust_vec_len, data_len),
|
||||||
56 => wire__crate__bridge__api__rust_api_force_ipa_check_impl(port, ptr, rust_vec_len, data_len),
|
56 => wire__crate__bridge__api__rust_api_establish_signal_session_impl(port, ptr, rust_vec_len, data_len),
|
||||||
57 => wire__crate__bridge__api__rust_api_get_memories_url_impl(port, ptr, rust_vec_len, data_len),
|
57 => wire__crate__bridge__api__rust_api_events_impl(port, ptr, rust_vec_len, data_len),
|
||||||
58 => wire__crate__bridge__api__rust_api_get_memories_usage_impl(port, ptr, rust_vec_len, data_len),
|
58 => wire__crate__bridge__api__rust_api_finish_started_media_uploads_impl(port, ptr, rust_vec_len, data_len),
|
||||||
59 => wire__crate__bridge__api__rust_api_get_plan_balance_impl(port, ptr, rust_vec_len, data_len),
|
59 => wire__crate__bridge__api__rust_api_force_ipa_check_impl(port, ptr, rust_vec_len, data_len),
|
||||||
60 => wire__crate__bridge__api__rust_api_get_proof_of_work_impl(port, ptr, rust_vec_len, data_len),
|
60 => wire__crate__bridge__api__rust_api_get_memories_url_impl(port, ptr, rust_vec_len, data_len),
|
||||||
61 => wire__crate__bridge__api__rust_api_get_server_key_for_passwordless_recovery_impl(port, ptr, rust_vec_len, data_len),
|
61 => wire__crate__bridge__api__rust_api_get_memories_usage_impl(port, ptr, rust_vec_len, data_len),
|
||||||
62 => wire__crate__bridge__api__rust_api_get_user_by_id_impl(port, ptr, rust_vec_len, data_len),
|
62 => wire__crate__bridge__api__rust_api_get_plan_balance_impl(port, ptr, rust_vec_len, data_len),
|
||||||
63 => wire__crate__bridge__api__rust_api_get_user_data_impl(port, ptr, rust_vec_len, data_len),
|
63 => wire__crate__bridge__api__rust_api_get_proof_of_work_impl(port, ptr, rust_vec_len, data_len),
|
||||||
64 => wire__crate__bridge__api__rust_api_get_user_id_from_username_impl(port, ptr, rust_vec_len, data_len),
|
64 => wire__crate__bridge__api__rust_api_get_server_key_for_passwordless_recovery_impl(port, ptr, rust_vec_len, data_len),
|
||||||
65 => wire__crate__bridge__api__rust_api_hand_outbox_to_os_impl(port, ptr, rust_vec_len, data_len),
|
65 => wire__crate__bridge__api__rust_api_get_user_by_id_impl(port, ptr, rust_vec_len, data_len),
|
||||||
66 => wire__crate__bridge__api__rust_api_initialize_media_upload_impl(port, ptr, rust_vec_len, data_len),
|
66 => wire__crate__bridge__api__rust_api_get_user_data_impl(port, ptr, rust_vec_len, data_len),
|
||||||
67 => wire__crate__bridge__api__rust_api_insert_and_send_additional_data_impl(port, ptr, rust_vec_len, data_len),
|
67 => wire__crate__bridge__api__rust_api_get_user_id_from_username_impl(port, ptr, rust_vec_len, data_len),
|
||||||
68 => wire__crate__bridge__api__rust_api_insert_and_send_ask_about_user_impl(port, ptr, rust_vec_len, data_len),
|
68 => wire__crate__bridge__api__rust_api_hand_outbox_to_os_impl(port, ptr, rust_vec_len, data_len),
|
||||||
69 => wire__crate__bridge__api__rust_api_insert_and_send_contact_share_impl(port, ptr, rust_vec_len, data_len),
|
69 => wire__crate__bridge__api__rust_api_initialize_media_upload_impl(port, ptr, rust_vec_len, data_len),
|
||||||
70 => wire__crate__bridge__api__rust_api_insert_and_send_text_impl(port, ptr, rust_vec_len, data_len),
|
70 => wire__crate__bridge__api__rust_api_insert_and_send_additional_data_impl(port, ptr, rust_vec_len, data_len),
|
||||||
71 => wire__crate__bridge__api__rust_api_ipa_purchase_impl(port, ptr, rust_vec_len, data_len),
|
71 => wire__crate__bridge__api__rust_api_insert_and_send_ask_about_user_impl(port, ptr, rust_vec_len, data_len),
|
||||||
72 => wire__crate__bridge__api__rust_api_load_plan_balance_impl(port, ptr, rust_vec_len, data_len),
|
72 => wire__crate__bridge__api__rust_api_insert_and_send_contact_share_impl(port, ptr, rust_vec_len, data_len),
|
||||||
73 => wire__crate__bridge__api__rust_api_media_size_limit_report_impl(port, ptr, rust_vec_len, data_len),
|
73 => wire__crate__bridge__api__rust_api_insert_and_send_text_impl(port, ptr, rust_vec_len, data_len),
|
||||||
74 => wire__crate__bridge__api__rust_api_media_step_finished_impl(port, ptr, rust_vec_len, data_len),
|
74 => wire__crate__bridge__api__rust_api_ipa_purchase_impl(port, ptr, rust_vec_len, data_len),
|
||||||
75 => wire__crate__bridge__api__rust_api_notification_badge_count_impl(port, ptr, rust_vec_len, data_len),
|
75 => wire__crate__bridge__api__rust_api_load_plan_balance_impl(port, ptr, rust_vec_len, data_len),
|
||||||
76 => wire__crate__bridge__api__rust_api_notify_messages_opened_impl(port, ptr, rust_vec_len, data_len),
|
76 => wire__crate__bridge__api__rust_api_media_size_limit_report_impl(port, ptr, rust_vec_len, data_len),
|
||||||
77 => wire__crate__bridge__api__rust_api_perform_passwordless_recovery_heartbeat_impl(port, ptr, rust_vec_len, data_len),
|
77 => wire__crate__bridge__api__rust_api_media_step_finished_impl(port, ptr, rust_vec_len, data_len),
|
||||||
78 => wire__crate__bridge__api__rust_api_prerender_media_impl(port, ptr, rust_vec_len, data_len),
|
78 => wire__crate__bridge__api__rust_api_notification_badge_count_impl(port, ptr, rust_vec_len, data_len),
|
||||||
79 => wire__crate__bridge__api__rust_api_purge_media_temp_folder_impl(port, ptr, rust_vec_len, data_len),
|
79 => wire__crate__bridge__api__rust_api_notify_messages_opened_impl(port, ptr, rust_vec_len, data_len),
|
||||||
80 => wire__crate__bridge__api__rust_api_purge_widget_media_impl(port, ptr, rust_vec_len, data_len),
|
80 => wire__crate__bridge__api__rust_api_perform_passwordless_recovery_heartbeat_impl(port, ptr, rust_vec_len, data_len),
|
||||||
81 => wire__crate__bridge__api__rust_api_refresh_widget_manifest_impl(port, ptr, rust_vec_len, data_len),
|
81 => wire__crate__bridge__api__rust_api_prerender_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
82 => wire__crate__bridge__api__rust_api_register_impl(port, ptr, rust_vec_len, data_len),
|
82 => wire__crate__bridge__api__rust_api_purge_media_temp_folder_impl(port, ptr, rust_vec_len, data_len),
|
||||||
83 => wire__crate__bridge__api__rust_api_register_home_widget_impl(port, ptr, rust_vec_len, data_len),
|
83 => wire__crate__bridge__api__rust_api_purge_widget_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
84 => wire__crate__bridge__api__rust_api_register_passwordless_notification_impl(port, ptr, rust_vec_len, data_len),
|
84 => wire__crate__bridge__api__rust_api_refresh_widget_manifest_impl(port, ptr, rust_vec_len, data_len),
|
||||||
85 => wire__crate__bridge__api__rust_api_register_passwordless_recovery_impl(port, ptr, rust_vec_len, data_len),
|
85 => wire__crate__bridge__api__rust_api_register_impl(port, ptr, rust_vec_len, data_len),
|
||||||
86 => wire__crate__bridge__api__rust_api_reload_configuration_impl(port, ptr, rust_vec_len, data_len),
|
86 => wire__crate__bridge__api__rust_api_register_home_widget_impl(port, ptr, rust_vec_len, data_len),
|
||||||
87 => wire__crate__bridge__api__rust_api_remove_additional_user_impl(port, ptr, rust_vec_len, data_len),
|
87 => wire__crate__bridge__api__rust_api_register_passwordless_notification_impl(port, ptr, rust_vec_len, data_len),
|
||||||
88 => wire__crate__bridge__api__rust_api_remove_media_files_impl(port, ptr, rust_vec_len, data_len),
|
88 => wire__crate__bridge__api__rust_api_register_passwordless_recovery_impl(port, ptr, rust_vec_len, data_len),
|
||||||
89 => wire__crate__bridge__api__rust_api_report_user_impl(port, ptr, rust_vec_len, data_len),
|
89 => wire__crate__bridge__api__rust_api_reload_configuration_impl(port, ptr, rust_vec_len, data_len),
|
||||||
90 => wire__crate__bridge__api__rust_api_request_binary_impl(port, ptr, rust_vec_len, data_len),
|
90 => wire__crate__bridge__api__rust_api_remove_additional_user_impl(port, ptr, rust_vec_len, data_len),
|
||||||
91 => wire__crate__bridge__api__rust_api_request_contact_by_username_impl(port, ptr, rust_vec_len, data_len),
|
91 => wire__crate__bridge__api__rust_api_remove_media_files_impl(port, ptr, rust_vec_len, data_len),
|
||||||
92 => wire__crate__bridge__api__rust_api_request_media_reupload_impl(port, ptr, rust_vec_len, data_len),
|
92 => wire__crate__bridge__api__rust_api_report_user_impl(port, ptr, rust_vec_len, data_len),
|
||||||
93 => wire__crate__bridge__api__rust_api_request_memories_upload_impl(port, ptr, rust_vec_len, data_len),
|
93 => wire__crate__bridge__api__rust_api_request_binary_impl(port, ptr, rust_vec_len, data_len),
|
||||||
94 => wire__crate__bridge__api__rust_api_retransmit_all_messages_impl(port, ptr, rust_vec_len, data_len),
|
94 => wire__crate__bridge__api__rust_api_request_contact_by_username_impl(port, ptr, rust_vec_len, data_len),
|
||||||
95 => wire__crate__bridge__api__rust_api_retry_pending_media_reuploads_impl(port, ptr, rust_vec_len, data_len),
|
95 => wire__crate__bridge__api__rust_api_request_media_reupload_impl(port, ptr, rust_vec_len, data_len),
|
||||||
96 => wire__crate__bridge__api__rust_api_reupload_pending_media_impl(port, ptr, rust_vec_len, data_len),
|
96 => wire__crate__bridge__api__rust_api_request_memories_upload_impl(port, ptr, rust_vec_len, data_len),
|
||||||
97 => wire__crate__bridge__api__rust_api_save_media_to_gallery_impl(port, ptr, rust_vec_len, data_len),
|
97 => wire__crate__bridge__api__rust_api_retransmit_all_messages_impl(port, ptr, rust_vec_len, data_len),
|
||||||
98 => wire__crate__bridge__api__rust_api_send_binary_impl(port, ptr, rust_vec_len, data_len),
|
98 => wire__crate__bridge__api__rust_api_retry_pending_media_reuploads_impl(port, ptr, rust_vec_len, data_len),
|
||||||
99 => wire__crate__bridge__api__rust_api_send_contact_profile_impl(port, ptr, rust_vec_len, data_len),
|
99 => wire__crate__bridge__api__rust_api_reupload_pending_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
100 => wire__crate__bridge__api__rust_api_send_encrypted_content_impl(port, ptr, rust_vec_len, data_len),
|
100 => wire__crate__bridge__api__rust_api_save_media_to_gallery_impl(port, ptr, rust_vec_len, data_len),
|
||||||
101 => wire__crate__bridge__api__rust_api_send_encrypted_content_to_group_impl(port, ptr, rust_vec_len, data_len),
|
101 => wire__crate__bridge__api__rust_api_send_binary_impl(port, ptr, rust_vec_len, data_len),
|
||||||
102 => wire__crate__bridge__api__rust_api_send_media_to_groups_impl(port, ptr, rust_vec_len, data_len),
|
102 => wire__crate__bridge__api__rust_api_send_contact_profile_impl(port, ptr, rust_vec_len, data_len),
|
||||||
103 => wire__crate__bridge__api__rust_api_send_queued_message_impl(port, ptr, rust_vec_len, data_len),
|
103 => wire__crate__bridge__api__rust_api_send_encrypted_content_impl(port, ptr, rust_vec_len, data_len),
|
||||||
104 => wire__crate__bridge__api__rust_api_send_text_message_impl(port, ptr, rust_vec_len, data_len),
|
104 => wire__crate__bridge__api__rust_api_send_encrypted_content_to_group_impl(port, ptr, rust_vec_len, data_len),
|
||||||
105 => wire__crate__bridge__api__rust_api_send_typing_impl(port, ptr, rust_vec_len, data_len),
|
105 => wire__crate__bridge__api__rust_api_send_media_to_groups_impl(port, ptr, rust_vec_len, data_len),
|
||||||
106 => wire__crate__bridge__api__rust_api_set_background_impl(port, ptr, rust_vec_len, data_len),
|
106 => wire__crate__bridge__api__rust_api_send_queued_message_impl(port, ptr, rust_vec_len, data_len),
|
||||||
107 => wire__crate__bridge__api__rust_api_set_home_widget_groups_impl(port, ptr, rust_vec_len, data_len),
|
107 => wire__crate__bridge__api__rust_api_send_text_message_impl(port, ptr, rust_vec_len, data_len),
|
||||||
108 => wire__crate__bridge__api__rust_api_set_login_token_impl(port, ptr, rust_vec_len, data_len),
|
108 => wire__crate__bridge__api__rust_api_send_typing_impl(port, ptr, rust_vec_len, data_len),
|
||||||
109 => wire__crate__bridge__api__rust_api_set_media_display_limit_impl(port, ptr, rust_vec_len, data_len),
|
109 => wire__crate__bridge__api__rust_api_set_background_impl(port, ptr, rust_vec_len, data_len),
|
||||||
110 => wire__crate__bridge__api__rust_api_set_media_requires_authentication_impl(port, ptr, rust_vec_len, data_len),
|
110 => wire__crate__bridge__api__rust_api_set_home_widget_groups_impl(port, ptr, rust_vec_len, data_len),
|
||||||
111 => wire__crate__bridge__api__rust_api_set_media_trim_impl(port, ptr, rust_vec_len, data_len),
|
111 => wire__crate__bridge__api__rust_api_set_login_token_impl(port, ptr, rust_vec_len, data_len),
|
||||||
112 => wire__crate__bridge__api__rust_api_set_network_available_impl(port, ptr, rust_vec_len, data_len),
|
112 => wire__crate__bridge__api__rust_api_set_media_display_limit_impl(port, ptr, rust_vec_len, data_len),
|
||||||
113 => wire__crate__bridge__api__rust_api_store_media_impl(port, ptr, rust_vec_len, data_len),
|
113 => wire__crate__bridge__api__rust_api_set_media_requires_authentication_impl(port, ptr, rust_vec_len, data_len),
|
||||||
114 => wire__crate__bridge__api__rust_api_submit_recovery_share_impl(port, ptr, rust_vec_len, data_len),
|
114 => wire__crate__bridge__api__rust_api_set_media_trim_impl(port, ptr, rust_vec_len, data_len),
|
||||||
115 => wire__crate__bridge__api__rust_api_sync_widget_permissions_impl(port, ptr, rust_vec_len, data_len),
|
115 => wire__crate__bridge__api__rust_api_set_network_available_impl(port, ptr, rust_vec_len, data_len),
|
||||||
116 => wire__crate__bridge__api__rust_api_toggle_media_remove_audio_impl(port, ptr, rust_vec_len, data_len),
|
116 => wire__crate__bridge__api__rust_api_store_media_impl(port, ptr, rust_vec_len, data_len),
|
||||||
117 => wire__crate__bridge__api__rust_api_try_request_contact_by_id_impl(port, ptr, rust_vec_len, data_len),
|
117 => wire__crate__bridge__api__rust_api_submit_recovery_share_impl(port, ptr, rust_vec_len, data_len),
|
||||||
118 => wire__crate__bridge__api__rust_api_unregister_home_widget_impl(port, ptr, rust_vec_len, data_len),
|
118 => wire__crate__bridge__api__rust_api_sync_widget_permissions_impl(port, ptr, rust_vec_len, data_len),
|
||||||
119 => wire__crate__bridge__api__rust_api_update_fcm_token_impl(port, ptr, rust_vec_len, data_len),
|
119 => wire__crate__bridge__api__rust_api_toggle_media_remove_audio_impl(port, ptr, rust_vec_len, data_len),
|
||||||
120 => wire__crate__bridge__api__rust_api_update_signed_pre_key_impl(port, ptr, rust_vec_len, data_len),
|
120 => wire__crate__bridge__api__rust_api_try_request_contact_by_id_impl(port, ptr, rust_vec_len, data_len),
|
||||||
121 => wire__crate__bridge__api__rust_api_upload_pqc_pre_keys_impl(port, ptr, rust_vec_len, data_len),
|
121 => wire__crate__bridge__api__rust_api_unregister_home_widget_impl(port, ptr, rust_vec_len, data_len),
|
||||||
122 => wire__crate__bridge__wrapper__app_database__rust_app_database_changes_impl(port, ptr, rust_vec_len, data_len),
|
122 => wire__crate__bridge__api__rust_api_update_fcm_token_impl(port, ptr, rust_vec_len, data_len),
|
||||||
123 => wire__crate__bridge__wrapper__app_database__rust_app_database_execute_impl(port, ptr, rust_vec_len, data_len),
|
123 => wire__crate__bridge__api__rust_api_update_signed_pre_key_impl(port, ptr, rust_vec_len, data_len),
|
||||||
124 => wire__crate__bridge__wrapper__app_database__rust_app_database_legacy_import_complete_impl(port, ptr, rust_vec_len, data_len),
|
124 => wire__crate__bridge__api__rust_api_upload_pqc_pre_keys_impl(port, ptr, rust_vec_len, data_len),
|
||||||
125 => wire__crate__bridge__wrapper__app_database__rust_app_database_migrate_legacy_database_impl(port, ptr, rust_vec_len, data_len),
|
125 => wire__crate__bridge__wrapper__app_database__rust_app_database_changes_impl(port, ptr, rust_vec_len, data_len),
|
||||||
126 => wire__crate__bridge__wrapper__app_database__rust_app_database_select_impl(port, ptr, rust_vec_len, data_len),
|
126 => wire__crate__bridge__wrapper__app_database__rust_app_database_execute_impl(port, ptr, rust_vec_len, data_len),
|
||||||
127 => wire__crate__bridge__wrapper__backup__rust_backup_archive_create_backup_archive_impl(port, ptr, rust_vec_len, data_len),
|
127 => wire__crate__bridge__wrapper__app_database__rust_app_database_legacy_import_complete_impl(port, ptr, rust_vec_len, data_len),
|
||||||
128 => wire__crate__bridge__wrapper__backup__rust_backup_archive_get_backup_download_token_impl(port, ptr, rust_vec_len, data_len),
|
128 => wire__crate__bridge__wrapper__app_database__rust_app_database_migrate_legacy_database_impl(port, ptr, rust_vec_len, data_len),
|
||||||
129 => wire__crate__bridge__wrapper__backup__rust_backup_archive_restore_backup_archive_impl(port, ptr, rust_vec_len, data_len),
|
129 => wire__crate__bridge__wrapper__app_database__rust_app_database_select_impl(port, ptr, rust_vec_len, data_len),
|
||||||
130 => wire__crate__bridge__wrapper__backup__rust_backup_identity_get_backup_id_impl(port, ptr, rust_vec_len, data_len),
|
130 => wire__crate__bridge__wrapper__backup__rust_backup_archive_create_backup_archive_impl(port, ptr, rust_vec_len, data_len),
|
||||||
131 => wire__crate__bridge__wrapper__backup__rust_backup_identity_get_backup_password_keys_impl(port, ptr, rust_vec_len, data_len),
|
131 => wire__crate__bridge__wrapper__backup__rust_backup_archive_get_backup_download_token_impl(port, ptr, rust_vec_len, data_len),
|
||||||
132 => wire__crate__bridge__wrapper__backup__rust_backup_identity_get_identity_backup_bytes_impl(port, ptr, rust_vec_len, data_len),
|
132 => wire__crate__bridge__wrapper__backup__rust_backup_archive_restore_backup_archive_impl(port, ptr, rust_vec_len, data_len),
|
||||||
133 => wire__crate__bridge__wrapper__backup__rust_backup_identity_import_backup_password_keys_impl(port, ptr, rust_vec_len, data_len),
|
133 => wire__crate__bridge__wrapper__backup__rust_backup_identity_get_backup_id_impl(port, ptr, rust_vec_len, data_len),
|
||||||
134 => wire__crate__bridge__wrapper__backup__rust_backup_identity_restore_identity_backup_impl(port, ptr, rust_vec_len, data_len),
|
134 => wire__crate__bridge__wrapper__backup__rust_backup_identity_get_backup_password_keys_impl(port, ptr, rust_vec_len, data_len),
|
||||||
135 => wire__crate__bridge__wrapper__backup__rust_backup_identity_set_backup_password_keys_impl(port, ptr, rust_vec_len, data_len),
|
135 => wire__crate__bridge__wrapper__backup__rust_backup_identity_get_identity_backup_bytes_impl(port, ptr, rust_vec_len, data_len),
|
||||||
136 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_decrypt_cloud_media_key_impl(port, ptr, rust_vec_len, data_len),
|
136 => wire__crate__bridge__wrapper__backup__rust_backup_identity_import_backup_password_keys_impl(port, ptr, rust_vec_len, data_len),
|
||||||
137 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_encrypt_cloud_media_key_impl(port, ptr, rust_vec_len, data_len),
|
137 => wire__crate__bridge__wrapper__backup__rust_backup_identity_restore_identity_backup_impl(port, ptr, rust_vec_len, data_len),
|
||||||
138 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_get_signal_identity_impl(port, ptr, rust_vec_len, data_len),
|
138 => wire__crate__bridge__wrapper__backup__rust_backup_identity_set_backup_password_keys_impl(port, ptr, rust_vec_len, data_len),
|
||||||
139 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_get_user_id_impl(port, ptr, rust_vec_len, data_len),
|
139 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_decrypt_cloud_media_key_impl(port, ptr, rust_vec_len, data_len),
|
||||||
140 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_import_serialized_impl(port, ptr, rust_vec_len, data_len),
|
140 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_encrypt_cloud_media_key_impl(port, ptr, rust_vec_len, data_len),
|
||||||
141 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_import_signal_identity_impl(port, ptr, rust_vec_len, data_len),
|
141 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_get_signal_identity_impl(port, ptr, rust_vec_len, data_len),
|
||||||
142 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_remove_local_credentials_impl(port, ptr, rust_vec_len, data_len),
|
142 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_get_user_id_impl(port, ptr, rust_vec_len, data_len),
|
||||||
143 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_serialize_impl(port, ptr, rust_vec_len, data_len),
|
143 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_import_serialized_impl(port, ptr, rust_vec_len, data_len),
|
||||||
144 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_set_user_id_impl(port, ptr, rust_vec_len, data_len),
|
144 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_import_signal_identity_impl(port, ptr, rust_vec_len, data_len),
|
||||||
145 => wire__crate__bridge__wrapper__signal__rust_signal_decrypt_impl(port, ptr, rust_vec_len, data_len),
|
145 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_remove_local_credentials_impl(port, ptr, rust_vec_len, data_len),
|
||||||
146 => wire__crate__bridge__wrapper__signal__rust_signal_encrypt_impl(port, ptr, rust_vec_len, data_len),
|
146 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_serialize_impl(port, ptr, rust_vec_len, data_len),
|
||||||
147 => wire__crate__bridge__wrapper__signal__rust_signal_generate_bundle_impl(port, ptr, rust_vec_len, data_len),
|
147 => wire__crate__bridge__wrapper__key_manager__rust_key_manager_set_user_id_impl(port, ptr, rust_vec_len, data_len),
|
||||||
148 => wire__crate__bridge__wrapper__signal__rust_signal_generate_pqc_prekeys_impl(port, ptr, rust_vec_len, data_len),
|
148 => wire__crate__bridge__wrapper__signal__rust_signal_decrypt_impl(port, ptr, rust_vec_len, data_len),
|
||||||
149 => wire__crate__bridge__wrapper__signal__rust_signal_get_contact_public_key_impl(port, ptr, rust_vec_len, data_len),
|
149 => wire__crate__bridge__wrapper__signal__rust_signal_encrypt_impl(port, ptr, rust_vec_len, data_len),
|
||||||
150 => wire__crate__bridge__wrapper__signal__rust_signal_get_user_public_key_impl(port, ptr, rust_vec_len, data_len),
|
150 => wire__crate__bridge__wrapper__signal__rust_signal_generate_bundle_impl(port, ptr, rust_vec_len, data_len),
|
||||||
151 => wire__crate__bridge__wrapper__signal__rust_signal_process_prekey_bundle_impl(port, ptr, rust_vec_len, data_len),
|
151 => wire__crate__bridge__wrapper__signal__rust_signal_generate_pqc_prekeys_impl(port, ptr, rust_vec_len, data_len),
|
||||||
152 => wire__crate__bridge__wrapper__rust_utils_generate_shares_impl(port, ptr, rust_vec_len, data_len),
|
152 => wire__crate__bridge__wrapper__signal__rust_signal_get_contact_public_key_impl(port, ptr, rust_vec_len, data_len),
|
||||||
153 => wire__crate__bridge__wrapper__rust_utils_recover_secret_impl(port, ptr, rust_vec_len, data_len),
|
153 => wire__crate__bridge__wrapper__signal__rust_signal_get_user_public_key_impl(port, ptr, rust_vec_len, data_len),
|
||||||
154 => wire__crate__bridge__webxdc__send_update_impl(port, ptr, rust_vec_len, data_len),
|
154 => wire__crate__bridge__wrapper__signal__rust_signal_process_prekey_bundle_impl(port, ptr, rust_vec_len, data_len),
|
||||||
155 => wire__crate__bridge__webxdc__serve_impl(port, ptr, rust_vec_len, data_len),
|
155 => wire__crate__bridge__wrapper__rust_utils_generate_shares_impl(port, ptr, rust_vec_len, data_len),
|
||||||
156 => wire__crate__bridge__groups__update_chat_deletion_time_impl(port, ptr, rust_vec_len, data_len),
|
156 => wire__crate__bridge__wrapper__rust_utils_recover_secret_impl(port, ptr, rust_vec_len, data_len),
|
||||||
157 => wire__crate__bridge__groups__update_group_name_impl(port, ptr, rust_vec_len, data_len),
|
157 => wire__crate__bridge__webxdc__send_update_impl(port, ptr, rust_vec_len, data_len),
|
||||||
158 => wire__crate__bridge__webxdc__updates_after_impl(port, ptr, rust_vec_len, data_len),
|
158 => wire__crate__bridge__webxdc__serve_impl(port, ptr, rust_vec_len, data_len),
|
||||||
160 => wire__crate__bridge__user_config__user_config_api_create_impl(port, ptr, rust_vec_len, data_len),
|
159 => wire__crate__bridge__groups__update_chat_deletion_time_impl(port, ptr, rust_vec_len, data_len),
|
||||||
161 => wire__crate__bridge__user_config__user_config_api_import_json_impl(port, ptr, rust_vec_len, data_len),
|
160 => wire__crate__bridge__groups__update_group_name_impl(port, ptr, rust_vec_len, data_len),
|
||||||
162 => wire__crate__bridge__user_config__user_config_api_load_impl(port, ptr, rust_vec_len, data_len),
|
161 => wire__crate__bridge__webxdc__updates_after_impl(port, ptr, rust_vec_len, data_len),
|
||||||
163 => wire__crate__bridge__user_config__user_config_api_save_impl(port, ptr, rust_vec_len, data_len),
|
163 => wire__crate__bridge__user_config__user_config_api_create_impl(port, ptr, rust_vec_len, data_len),
|
||||||
164 => wire__crate__bridge__user_config__user_config_api_update_impl(port, ptr, rust_vec_len, data_len),
|
164 => wire__crate__bridge__user_config__user_config_api_import_json_impl(port, ptr, rust_vec_len, data_len),
|
||||||
|
165 => wire__crate__bridge__user_config__user_config_api_load_impl(port, ptr, rust_vec_len, data_len),
|
||||||
|
166 => wire__crate__bridge__user_config__user_config_api_save_impl(port, ptr, rust_vec_len, data_len),
|
||||||
|
167 => wire__crate__bridge__user_config__user_config_api_update_impl(port, ptr, rust_vec_len, data_len),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7569,17 +7726,17 @@ fn pde_ffi_dispatcher_sync_impl(
|
||||||
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
|
) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
|
||||||
// Codec=Pde (Serialization + dispatch), see doc to use other codecs
|
// Codec=Pde (Serialization + dispatch), see doc to use other codecs
|
||||||
match func_id {
|
match func_id {
|
||||||
30 => wire__crate__bridge__api__rust_api_api_base_url_impl(ptr, rust_vec_len, data_len),
|
33 => wire__crate__bridge__api__rust_api_api_base_url_impl(ptr, rust_vec_len, data_len),
|
||||||
32 => wire__crate__bridge__api__rust_api_avatar_png_path_impl(ptr, rust_vec_len, data_len),
|
35 => wire__crate__bridge__api__rust_api_avatar_png_path_impl(ptr, rust_vec_len, data_len),
|
||||||
44 => {
|
47 => {
|
||||||
wire__crate__bridge__api__rust_api_decode_avatar_svg_impl(ptr, rust_vec_len, data_len)
|
wire__crate__bridge__api__rust_api_decode_avatar_svg_impl(ptr, rust_vec_len, data_len)
|
||||||
}
|
}
|
||||||
159 => wire__crate__bridge__user_config__user_config_api_clone_impl(
|
162 => wire__crate__bridge__user_config__user_config_api_clone_impl(
|
||||||
ptr,
|
ptr,
|
||||||
rust_vec_len,
|
rust_vec_len,
|
||||||
data_len,
|
data_len,
|
||||||
),
|
),
|
||||||
165 => wire__crate__bridge__logging__write_log_impl(ptr, rust_vec_len, data_len),
|
168 => wire__crate__bridge__logging__write_log_impl(ptr, rust_vec_len, data_len),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8528,6 +8685,30 @@ impl flutter_rust_bridge::IntoIntoDart<crate::bridge::webxdc::WebxdcInstanceInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||||
|
impl flutter_rust_bridge::IntoDart for crate::bridge::webxdc::WebxdcOneTimeInstance {
|
||||||
|
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||||
|
[
|
||||||
|
self.instance_id.into_into_dart().into_dart(),
|
||||||
|
self.name.into_into_dart().into_dart(),
|
||||||
|
self.icon.into_into_dart().into_dart(),
|
||||||
|
self.summary.into_into_dart().into_dart(),
|
||||||
|
self.document.into_into_dart().into_dart(),
|
||||||
|
]
|
||||||
|
.into_dart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive
|
||||||
|
for crate::bridge::webxdc::WebxdcOneTimeInstance
|
||||||
|
{
|
||||||
|
}
|
||||||
|
impl flutter_rust_bridge::IntoIntoDart<crate::bridge::webxdc::WebxdcOneTimeInstance>
|
||||||
|
for crate::bridge::webxdc::WebxdcOneTimeInstance
|
||||||
|
{
|
||||||
|
fn into_into_dart(self) -> crate::bridge::webxdc::WebxdcOneTimeInstance {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||||
impl flutter_rust_bridge::IntoDart for crate::bridge::webxdc::WebxdcResponse {
|
impl flutter_rust_bridge::IntoDart for crate::bridge::webxdc::WebxdcResponse {
|
||||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||||
[
|
[
|
||||||
|
|
@ -8562,6 +8743,9 @@ impl flutter_rust_bridge::IntoDart for crate::bridge::webxdc::WebxdcStoreApp {
|
||||||
self.source_code_url.into_into_dart().into_dart(),
|
self.source_code_url.into_into_dart().into_dart(),
|
||||||
self.icon.into_into_dart().into_dart(),
|
self.icon.into_into_dart().into_dart(),
|
||||||
self.bundle_bytes.into_into_dart().into_dart(),
|
self.bundle_bytes.into_into_dart().into_dart(),
|
||||||
|
self.pro_only.into_into_dart().into_dart(),
|
||||||
|
self.one_time.into_into_dart().into_dart(),
|
||||||
|
self.instance_id.into_into_dart().into_dart(),
|
||||||
]
|
]
|
||||||
.into_dart()
|
.into_dart()
|
||||||
}
|
}
|
||||||
|
|
@ -9047,6 +9231,16 @@ impl SseEncode for Vec<crate::database::app::SqlValue> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SseEncode for Vec<crate::bridge::webxdc::WebxdcOneTimeInstance> {
|
||||||
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
|
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||||
|
<i32>::sse_encode(self.len() as _, serializer);
|
||||||
|
for item in self {
|
||||||
|
<crate::bridge::webxdc::WebxdcOneTimeInstance>::sse_encode(item, serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SseEncode for Vec<crate::bridge::webxdc::WebxdcStoreApp> {
|
impl SseEncode for Vec<crate::bridge::webxdc::WebxdcStoreApp> {
|
||||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||||
|
|
@ -9570,6 +9764,17 @@ impl SseEncode for crate::bridge::webxdc::WebxdcInstanceInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SseEncode for crate::bridge::webxdc::WebxdcOneTimeInstance {
|
||||||
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
|
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||||
|
<String>::sse_encode(self.instance_id, serializer);
|
||||||
|
<String>::sse_encode(self.name, serializer);
|
||||||
|
<Option<Vec<u8>>>::sse_encode(self.icon, serializer);
|
||||||
|
<Option<String>>::sse_encode(self.summary, serializer);
|
||||||
|
<Option<String>>::sse_encode(self.document, serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SseEncode for crate::bridge::webxdc::WebxdcResponse {
|
impl SseEncode for crate::bridge::webxdc::WebxdcResponse {
|
||||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||||
|
|
@ -9591,6 +9796,9 @@ impl SseEncode for crate::bridge::webxdc::WebxdcStoreApp {
|
||||||
<Option<String>>::sse_encode(self.source_code_url, serializer);
|
<Option<String>>::sse_encode(self.source_code_url, serializer);
|
||||||
<Option<Vec<u8>>>::sse_encode(self.icon, serializer);
|
<Option<Vec<u8>>>::sse_encode(self.icon, serializer);
|
||||||
<i64>::sse_encode(self.bundle_bytes, serializer);
|
<i64>::sse_encode(self.bundle_bytes, serializer);
|
||||||
|
<bool>::sse_encode(self.pro_only, serializer);
|
||||||
|
<bool>::sse_encode(self.one_time, serializer);
|
||||||
|
<Option<String>>::sse_encode(self.instance_id, serializer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ impl MessageService {
|
||||||
|| content.media.is_some()
|
|| content.media.is_some()
|
||||||
|| content.text_message.is_some()
|
|| content.text_message.is_some()
|
||||||
{
|
{
|
||||||
sqlx::query!("UPDATE groups SET last_message_exchange = CAST(strftime('%s','now') AS INTEGER) WHERE group_id = ?", group_id)
|
sqlx::query!("UPDATE groups SET last_message_exchange = CAST(strftime('%s','now') AS INTEGER), deleted_content = 0 WHERE group_id = ?", group_id)
|
||||||
.execute(&database.pool).await?;
|
.execute(&database.pool).await?;
|
||||||
}
|
}
|
||||||
let members = sqlx::query_scalar!(
|
let members = sqlx::query_scalar!(
|
||||||
|
|
@ -412,6 +412,8 @@ impl MessageService {
|
||||||
webxdc_app: None,
|
webxdc_app: None,
|
||||||
webxdc_update: None,
|
webxdc_update: None,
|
||||||
webxdc_origin: None,
|
webxdc_origin: None,
|
||||||
|
webxdc_sync: None,
|
||||||
|
webxdc_sync_request: None,
|
||||||
}
|
}
|
||||||
.encode_to_vec();
|
.encode_to_vec();
|
||||||
self.insert_and_send_additional_data(group_id, "contacts".into(), data, false)
|
self.insert_and_send_additional_data(group_id, "contacts".into(), data, false)
|
||||||
|
|
@ -447,6 +449,8 @@ impl MessageService {
|
||||||
webxdc_app: None,
|
webxdc_app: None,
|
||||||
webxdc_update: None,
|
webxdc_update: None,
|
||||||
webxdc_origin: None,
|
webxdc_origin: None,
|
||||||
|
webxdc_sync: None,
|
||||||
|
webxdc_sync_request: None,
|
||||||
}
|
}
|
||||||
.encode_to_vec();
|
.encode_to_vec();
|
||||||
self.insert_and_send_additional_data(group_id, "askAboutUser".into(), data, false)
|
self.insert_and_send_additional_data(group_id, "askAboutUser".into(), data, false)
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,30 @@ static DE_TRANSLATIONS: LazyLock<HashMap<String, String>> =
|
||||||
/// The update itself is hidden -- app state rather than something a person
|
/// The update itself is hidden -- app state rather than something a person
|
||||||
/// sent -- but an `info` is written to be read, and becomes a chat row of its
|
/// sent -- but an `info` is written to be read, and becomes a chat row of its
|
||||||
/// own on arrival. That row is what the receiver is woken and notified for.
|
/// own on arrival. That row is what the receiver is woken and notified for.
|
||||||
fn webxdc_announcement(message: &encrypted_content::AdditionalDataMessage) -> Option<String> {
|
fn webxdc_announcement(
|
||||||
|
message: &encrypted_content::AdditionalDataMessage,
|
||||||
|
user_id: i64,
|
||||||
|
) -> Option<String> {
|
||||||
let data = <proto::AdditionalMessageData as prost::Message>::decode(
|
let data = <proto::AdditionalMessageData as prost::Message>::decode(
|
||||||
message.additional_message_data.as_deref()?,
|
message.additional_message_data.as_deref()?,
|
||||||
)
|
)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
crate::services::webxdc::announcement(&data.webxdc_update?)
|
let update = data.webxdc_update?;
|
||||||
|
// Keep chat announcements shared, but only wake recipients selected by the app.
|
||||||
|
let announcement = crate::services::webxdc::announcement(&update)?;
|
||||||
|
match update.notify.as_deref() {
|
||||||
|
None => Some(announcement),
|
||||||
|
Some(raw) => {
|
||||||
|
let recipients: std::collections::BTreeMap<String, String> =
|
||||||
|
serde_json::from_str(raw).ok()?;
|
||||||
|
let address =
|
||||||
|
crate::services::webxdc::WebxdcService::address_for(&update.instance_id, user_id);
|
||||||
|
let text = recipients.get(&address)?;
|
||||||
|
let mut notification = update;
|
||||||
|
notification.info = Some(text.clone());
|
||||||
|
crate::services::webxdc::announcement(¬ification)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Who wrote the message with this id, as this device has it.
|
/// Who wrote the message with this id, as this device has it.
|
||||||
|
|
@ -85,7 +103,9 @@ pub(crate) async fn should_wake_receiver(
|
||||||
|| content
|
|| content
|
||||||
.additional_data_message
|
.additional_data_message
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|message| !message.hidden || webxdc_announcement(message).is_some())
|
.is_some_and(|message| {
|
||||||
|
!message.hidden || webxdc_announcement(message, target_user_id).is_some()
|
||||||
|
})
|
||||||
|| content.group_create.is_some()
|
|| content.group_create.is_some()
|
||||||
|| content.media.as_ref().is_some_and(|value| {
|
|| content.media.as_ref().is_some_and(|value| {
|
||||||
// Widget media lands already opened and is deliberately recorded
|
// Widget media lands already opened and is deliberately recorded
|
||||||
|
|
@ -199,6 +219,7 @@ impl NotificationDraft {
|
||||||
/// transaction that commits that message. Transport retries are deduplicated
|
/// transaction that commits that message. Transport retries are deduplicated
|
||||||
/// by the receipt-derived event ID.
|
/// by the receipt-derived event ID.
|
||||||
pub(crate) async fn record_incoming_event(
|
pub(crate) async fn record_incoming_event(
|
||||||
|
ctx: &Context,
|
||||||
transaction: &mut Transaction<'_, Sqlite>,
|
transaction: &mut Transaction<'_, Sqlite>,
|
||||||
from_user_id: i64,
|
from_user_id: i64,
|
||||||
receipt_id: &str,
|
receipt_id: &str,
|
||||||
|
|
@ -270,9 +291,10 @@ pub(crate) async fn record_incoming_event(
|
||||||
// announcement -- and only once the row it materialised into exists,
|
// announcement -- and only once the row it materialised into exists,
|
||||||
// which it does not when the update was dropped for an unknown
|
// which it does not when the update was dropped for an unknown
|
||||||
// instance, a mismatched chat, or an app that is over budget.
|
// instance, a mismatched chat, or an app that is over budget.
|
||||||
|
let self_id = UserConfig::load_required_from(ctx)?.user_id;
|
||||||
let announcement = message
|
let announcement = message
|
||||||
.hidden
|
.hidden
|
||||||
.then(|| webxdc_announcement(message))
|
.then(|| webxdc_announcement(message, self_id))
|
||||||
.flatten();
|
.flatten();
|
||||||
let message_id = if message.hidden {
|
let message_id = if message.hidden {
|
||||||
crate::services::webxdc::WebxdcService::info_message_id(&message.sender_message_id)
|
crate::services::webxdc::WebxdcService::info_message_id(&message.sender_message_id)
|
||||||
|
|
@ -842,7 +864,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn announcement_of(content: &proto::EncryptedContent) -> Option<String> {
|
fn announcement_of(content: &proto::EncryptedContent) -> Option<String> {
|
||||||
webxdc_announcement(content.additional_data_message.as_ref().unwrap())
|
webxdc_announcement(content.additional_data_message.as_ref().unwrap(), 42)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -857,6 +879,62 @@ mod tests {
|
||||||
assert!(announcement_of(&webxdc_update(Some(" \u{200e} "))).is_none());
|
assert!(announcement_of(&webxdc_update(Some(" \u{200e} "))).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn targeted_update(notify: &str) -> proto::EncryptedContent {
|
||||||
|
let mut content = webxdc_update(Some("Dinner added"));
|
||||||
|
let message = content.additional_data_message.as_mut().unwrap();
|
||||||
|
let mut data = <proto::AdditionalMessageData as prost::Message>::decode(
|
||||||
|
message.additional_message_data.as_deref().unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
data.webxdc_update.as_mut().unwrap().notify = Some(notify.to_owned());
|
||||||
|
message.additional_message_data = Some(prost::Message::encode_to_vec(&data));
|
||||||
|
content
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn expense_notifications_only_wake_and_record_affected_members() -> Result<()> {
|
||||||
|
let directory = tempfile::tempdir()?;
|
||||||
|
let ctx =
|
||||||
|
Context::init_for_testing(directory.path().join("db"), directory.path().join("data"))
|
||||||
|
.await?;
|
||||||
|
UserConfig::save_json(
|
||||||
|
&ctx,
|
||||||
|
r#"{"userId":42,"username":"ben","displayName":"Ben"}"#,
|
||||||
|
)?;
|
||||||
|
let database = ctx.app_db.read().await.clone();
|
||||||
|
let mut tx = database.pool.begin().await?;
|
||||||
|
sqlx::query("INSERT INTO contacts(user_id, username) VALUES (7, 'anna')")
|
||||||
|
.execute(&mut *tx)
|
||||||
|
.await?;
|
||||||
|
sqlx::query("INSERT INTO groups(group_id, group_name) VALUES ('g', 'Trip')")
|
||||||
|
.execute(&mut *tx)
|
||||||
|
.await?;
|
||||||
|
sqlx::query("INSERT INTO messages(message_id, group_id, sender_id, type, content) VALUES ('message-info', 'g', 7, 'text', 'Dinner added')").execute(&mut *tx).await?;
|
||||||
|
let address = crate::services::webxdc::WebxdcService::address_for("instance", 42);
|
||||||
|
let raw = serde_json::json!({address: "You share dinner: €20"}).to_string();
|
||||||
|
let content = targeted_update(&raw);
|
||||||
|
assert!(should_wake_receiver(&mut tx, 42, &content).await?);
|
||||||
|
assert!(!should_wake_receiver(&mut tx, 43, &content).await?);
|
||||||
|
record_incoming_event(&ctx, &mut tx, 7, "included", &content).await?;
|
||||||
|
record_incoming_event(&ctx, &mut tx, 7, "included", &content).await?;
|
||||||
|
for raw in ["{}", "null", "not JSON", r#"{"someone-else":"Dinner"}"#] {
|
||||||
|
let content = targeted_update(raw);
|
||||||
|
assert!(!should_wake_receiver(&mut tx, 42, &content).await?);
|
||||||
|
record_incoming_event(&ctx, &mut tx, 7, "excluded", &content).await?;
|
||||||
|
}
|
||||||
|
let rows: Vec<(String, String)> =
|
||||||
|
sqlx::query_as("SELECT event_id, content FROM notification_outbox")
|
||||||
|
.fetch_all(&mut *tx)
|
||||||
|
.await?;
|
||||||
|
assert_eq!(
|
||||||
|
rows,
|
||||||
|
vec![("included".into(), "You share dinner: €20".into())]
|
||||||
|
);
|
||||||
|
// Older apps omit notify and retain their existing announcements.
|
||||||
|
assert!(should_wake_receiver(&mut tx, 43, &webxdc_update(Some("Your turn"))).await?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn pending_row(kind: &str) -> PendingRow {
|
fn pending_row(kind: &str) -> PendingRow {
|
||||||
PendingRow {
|
PendingRow {
|
||||||
event_id: "event".into(),
|
event_id: "event".into(),
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -134,7 +134,8 @@ impl WebxdcStore {
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
let now = chrono::Utc::now().timestamp();
|
let now = chrono::Utc::now().timestamp();
|
||||||
for entry in &catalog.entries {
|
for (position, entry) in catalog.entries.iter().enumerate() {
|
||||||
|
let sort_order = position as i64;
|
||||||
if !Self::entry_is_sane(entry) {
|
if !Self::entry_is_sane(entry) {
|
||||||
tracing::warn!(app_id = entry.app_id, "skipping unusable catalog entry");
|
tracing::warn!(app_id = entry.app_id, "skipping unusable catalog entry");
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -151,8 +152,8 @@ impl WebxdcStore {
|
||||||
r#"INSERT INTO webxdc_apps
|
r#"INSERT INTO webxdc_apps
|
||||||
(app_id, version, name, name_translations, source_code_url,
|
(app_id, version, name, name_translations, source_code_url,
|
||||||
description, icon, bundle_sha256, bundle_bytes, published,
|
description, icon, bundle_sha256, bundle_bytes, published,
|
||||||
cached_at)
|
cached_at, pro_only, sort_order, one_time)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?)
|
||||||
ON CONFLICT(app_id, version) DO UPDATE SET
|
ON CONFLICT(app_id, version) DO UPDATE SET
|
||||||
name = excluded.name,
|
name = excluded.name,
|
||||||
name_translations = excluded.name_translations,
|
name_translations = excluded.name_translations,
|
||||||
|
|
@ -162,6 +163,9 @@ impl WebxdcStore {
|
||||||
bundle_sha256 = excluded.bundle_sha256,
|
bundle_sha256 = excluded.bundle_sha256,
|
||||||
bundle_bytes = excluded.bundle_bytes,
|
bundle_bytes = excluded.bundle_bytes,
|
||||||
published = 1,
|
published = 1,
|
||||||
|
pro_only = excluded.pro_only,
|
||||||
|
sort_order = excluded.sort_order,
|
||||||
|
one_time = excluded.one_time,
|
||||||
cached_at = excluded.cached_at"#,
|
cached_at = excluded.cached_at"#,
|
||||||
entry.app_id,
|
entry.app_id,
|
||||||
entry.version,
|
entry.version,
|
||||||
|
|
@ -173,6 +177,9 @@ impl WebxdcStore {
|
||||||
entry.bundle_sha256,
|
entry.bundle_sha256,
|
||||||
entry.bundle_bytes,
|
entry.bundle_bytes,
|
||||||
now,
|
now,
|
||||||
|
entry.pro_only,
|
||||||
|
sort_order,
|
||||||
|
entry.one_time,
|
||||||
)
|
)
|
||||||
.execute(&mut *transaction)
|
.execute(&mut *transaction)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,10 @@
|
||||||
sendUpdateInterval: init.sendUpdateInterval,
|
sendUpdateInterval: init.sendUpdateInterval,
|
||||||
sendUpdateMaxSize: init.sendUpdateMaxSize,
|
sendUpdateMaxSize: init.sendUpdateMaxSize,
|
||||||
|
|
||||||
|
getMembers: function () {
|
||||||
|
return call('getMembers');
|
||||||
|
},
|
||||||
|
|
||||||
sendUpdate: function (update, descr) {
|
sendUpdate: function (update, descr) {
|
||||||
return call('sendUpdate', {
|
return call('sendUpdate', {
|
||||||
payload: update.payload === undefined ? null : update.payload,
|
payload: update.payload === undefined ? null : update.payload,
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ UserConfig testUserConfig({
|
||||||
currentSignedPreKeyIndexStart: 100000,
|
currentSignedPreKeyIndexStart: 100000,
|
||||||
hideChangeLog: true,
|
hideChangeLog: true,
|
||||||
hideMemoriesBackupPromo: false,
|
hideMemoriesBackupPromo: false,
|
||||||
|
hideWidgetShareExplainer: false,
|
||||||
updateFcmToken: true,
|
updateFcmToken: true,
|
||||||
canUseLoginTokenForAuth: true,
|
canUseLoginTokenForAuth: true,
|
||||||
isBackupEnabled: false,
|
isBackupEnabled: false,
|
||||||
|
|
|
||||||
|
|
@ -125,4 +125,32 @@ void main() {
|
||||||
expect(remainingIds.contains('msg_d_sender_deleted_expired'), isFalse);
|
expect(remainingIds.contains('msg_d_sender_deleted_expired'), isFalse);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('deleting a chat retains only one-time app state', () async {
|
||||||
|
await twonlyDB.groupsDao.createNewGroup(
|
||||||
|
GroupsCompanion.insert(groupId: 'chat', groupName: 'Trip'),
|
||||||
|
);
|
||||||
|
for (final statement in [
|
||||||
|
"INSERT INTO messages(message_id, group_id, type) VALUES ('text', 'chat', 'text')",
|
||||||
|
"INSERT INTO messages(message_id, group_id, type) VALUES ('expenses-card', 'chat', 'webxdcApp')",
|
||||||
|
"INSERT INTO messages(message_id, group_id, type) VALUES ('game-card', 'chat', 'webxdcApp')",
|
||||||
|
"INSERT INTO webxdc_apps(app_id, version, name, bundle_sha256, bundle_bytes, cached_at, one_time) VALUES ('expenses', 1, 'Expenses', 'expense-hash', 1, 0, 1)",
|
||||||
|
"INSERT INTO webxdc_apps(app_id, version, name, bundle_sha256, bundle_bytes, cached_at, one_time) VALUES ('game', 1, 'Game', 'game-hash', 1, 0, 0)",
|
||||||
|
"INSERT INTO webxdc_instances(instance_id, group_id, app_id, version, origin_token, created_at, last_update_at) VALUES ('expenses-card', 'chat', 'expenses', 1, 'expenses-origin', 0, 0)",
|
||||||
|
"INSERT INTO webxdc_instances(instance_id, group_id, app_id, version, origin_token, created_at, last_update_at) VALUES ('game-card', 'chat', 'game', 1, 'game-origin', 0, 0)",
|
||||||
|
"INSERT INTO webxdc_updates(instance_id, serial, message_id, payload, received_at) VALUES ('expenses-card', 1, 'expense-update', '{}', 0)",
|
||||||
|
]) {
|
||||||
|
await twonlyDB.customStatement(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
await twonlyDB.messagesDao.deleteMessagesByGroupId('chat');
|
||||||
|
|
||||||
|
final messages = await twonlyDB.select(twonlyDB.messages).get();
|
||||||
|
expect(messages.map((message) => message.messageId), ['expenses-card']);
|
||||||
|
final instances = await twonlyDB.select(twonlyDB.webxdcInstances).get();
|
||||||
|
expect(instances.map((instance) => instance.instanceId), ['expenses-card']);
|
||||||
|
final updates = await twonlyDB.select(twonlyDB.webxdcUpdates).get();
|
||||||
|
expect(updates, hasLength(1));
|
||||||
|
expect((await twonlyDB.groupsDao.getGroup('chat'))?.deletedContent, isTrue);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue