From b06c2e1cc8283bf292b582892fe5e46331518d3f Mon Sep 17 00:00:00 2001 From: otsmr Date: Fri, 24 Jan 2025 16:07:39 +0100 Subject: [PATCH] move files --- lib/src/model/json/message.dart | 106 +++++++++++ lib/src/model/json/message.g.dart | 56 ++++++ .../signal_identity.dart} | 18 +- .../signal_identity.g.dart} | 2 +- .../user_data.dart} | 17 +- .../user_data.g.dart} | 2 +- lib/src/providers/api_provider.dart | 5 +- lib/src/signal/signal_helper.dart | 172 +----------------- lib/src/utils/api.dart | 5 +- lib/src/utils/json.dart | 31 ++++ lib/src/utils/signal.dart | 142 +++++++++++++++ lib/src/utils/storage.dart | 2 +- lib/src/views/profile_view.dart | 2 +- 13 files changed, 356 insertions(+), 204 deletions(-) create mode 100644 lib/src/model/json/message.dart create mode 100644 lib/src/model/json/message.g.dart rename lib/src/model/{signal_identity_json.dart => json/signal_identity.dart} (58%) rename lib/src/model/{signal_identity_json.g.dart => json/signal_identity.g.dart} (95%) rename lib/src/model/{user_data_json.dart => json/user_data.dart} (63%) rename lib/src/model/{user_data_json.g.dart => json/user_data.g.dart} (95%) create mode 100644 lib/src/utils/json.dart create mode 100644 lib/src/utils/signal.dart diff --git a/lib/src/model/json/message.dart b/lib/src/model/json/message.dart new file mode 100644 index 0000000..96f05e3 --- /dev/null +++ b/lib/src/model/json/message.dart @@ -0,0 +1,106 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:twonly/src/utils/json.dart'; +part 'message.g.dart'; + +enum MessageKind { textMessage, image, video, contactRequest } + +// so _$MessageKindEnumMap gets generated +@JsonSerializable() +class _MessageKind { + MessageKind? kind; +} + +@JsonSerializable() +class Message { + @Int64Converter() + final Int64 fromUserId; + final MessageKind kind; + final MessageContent? content; + DateTime timestamp; + + Message( + {required this.fromUserId, + required this.kind, + this.content, + required this.timestamp}); + + @override + String toString() { + return 'Message(kind: $kind, content: $content, timestamp: $timestamp)'; + } + + Message fromJson(Map json) { + dynamic content; + MessageKind kind = $enumDecode(_$MessageKindEnumMap, json['kind']); + switch (kind) { + case MessageKind.textMessage: + content = TextContent.fromJson(json["content"]); + break; + case MessageKind.image: + content = ImageContent.fromJson(json["content"]); + break; + default: + } + + return Message( + fromUserId: const Int64Converter().fromJson(json['fromUserId'] as String), + kind: kind, + timestamp: DateTime.parse(json['timestamp'] as String), + content: content, + ); + } + + Map toJson(Message instance) { + var json = { + 'fromUserId': const Int64Converter().toJson(instance.fromUserId), + 'kind': _$MessageKindEnumMap[instance.kind]!, + 'timestamp': instance.timestamp.toIso8601String(), + 'content': instance.content + }; + + return json; + } +} + +abstract class MessageContent { + MessageContent(); + factory MessageContent.fromJson(Map json) { + return TextContent(""); + } + + Map toJson(); +} +// factory MessageContent.fromJson(Map json) => +// _$MessageContentFromJson(json); + +@JsonSerializable() +class TextContent extends MessageContent { + final String text; + + TextContent(this.text); + + factory TextContent.fromJson(Map json) => + _$TextContentFromJson(json); + @override + Map toJson() => _$TextContentToJson(this); +} + +@JsonSerializable() +class ImageContent extends MessageContent { + final String imageUrl; + + ImageContent(this.imageUrl); + + factory ImageContent.fromJson(Map json) => + _$ImageContentFromJson(json); + @override + Map toJson() => _$ImageContentToJson(this); +} + +// @JsonSerializable() +// class VideoContent extends MessageContent { +// final String videoUrl; + +// VideoContent(this.videoUrl); +// } diff --git a/lib/src/model/json/message.g.dart b/lib/src/model/json/message.g.dart new file mode 100644 index 0000000..2dc4a13 --- /dev/null +++ b/lib/src/model/json/message.g.dart @@ -0,0 +1,56 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'message.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_MessageKind _$MessageKindFromJson(Map json) => _MessageKind() + ..kind = $enumDecodeNullable(_$MessageKindEnumMap, json['kind']); + +Map _$MessageKindToJson(_MessageKind instance) => + { + 'kind': _$MessageKindEnumMap[instance.kind], + }; + +const _$MessageKindEnumMap = { + MessageKind.textMessage: 'textMessage', + MessageKind.image: 'image', + MessageKind.video: 'video', + MessageKind.contactRequest: 'contactRequest', +}; + +Message _$MessageFromJson(Map json) => Message( + fromUserId: const Int64Converter().fromJson(json['fromUserId'] as String), + kind: $enumDecode(_$MessageKindEnumMap, json['kind']), + content: json['content'] == null + ? null + : MessageContent.fromJson(json['content'] as Map), + timestamp: DateTime.parse(json['timestamp'] as String), + ); + +Map _$MessageToJson(Message instance) => { + 'fromUserId': const Int64Converter().toJson(instance.fromUserId), + 'kind': _$MessageKindEnumMap[instance.kind]!, + 'content': instance.content, + 'timestamp': instance.timestamp.toIso8601String(), + }; + +TextContent _$TextContentFromJson(Map json) => TextContent( + json['text'] as String, + ); + +Map _$TextContentToJson(TextContent instance) => + { + 'text': instance.text, + }; + +ImageContent _$ImageContentFromJson(Map json) => ImageContent( + json['imageUrl'] as String, + ); + +Map _$ImageContentToJson(ImageContent instance) => + { + 'imageUrl': instance.imageUrl, + }; diff --git a/lib/src/model/signal_identity_json.dart b/lib/src/model/json/signal_identity.dart similarity index 58% rename from lib/src/model/signal_identity_json.dart rename to lib/src/model/json/signal_identity.dart index dffd786..c8413e6 100644 --- a/lib/src/model/signal_identity_json.dart +++ b/lib/src/model/json/signal_identity.dart @@ -1,22 +1,8 @@ -import 'dart:convert'; import 'dart:typed_data'; import 'package:fixnum/fixnum.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:twonly/src/model/user_data_json.dart'; -part 'signal_identity_json.g.dart'; - -class Uint8ListConverter implements JsonConverter { - const Uint8ListConverter(); - @override - Uint8List fromJson(String json) { - return base64Decode(json); - } - - @override - String toJson(Uint8List object) { - return base64Encode(object); - } -} +import 'package:twonly/src/utils/json.dart'; +part 'signal_identity.g.dart'; @JsonSerializable() class SignalIdentity { diff --git a/lib/src/model/signal_identity_json.g.dart b/lib/src/model/json/signal_identity.g.dart similarity index 95% rename from lib/src/model/signal_identity_json.g.dart rename to lib/src/model/json/signal_identity.g.dart index 3aef2a0..7c0c868 100644 --- a/lib/src/model/signal_identity_json.g.dart +++ b/lib/src/model/json/signal_identity.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'signal_identity_json.dart'; +part of 'signal_identity.dart'; // ************************************************************************** // JsonSerializableGenerator diff --git a/lib/src/model/user_data_json.dart b/lib/src/model/json/user_data.dart similarity index 63% rename from lib/src/model/user_data_json.dart rename to lib/src/model/json/user_data.dart index 44bd02c..d18476f 100644 --- a/lib/src/model/user_data_json.dart +++ b/lib/src/model/json/user_data.dart @@ -1,20 +1,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:fixnum/fixnum.dart'; -part 'user_data_json.g.dart'; - -class Int64Converter implements JsonConverter { - const Int64Converter(); - - @override - Int64 fromJson(String json) { - return Int64.parseInt(json); - } - - @override - String toJson(Int64 object) { - return object.toString(); - } -} +import 'package:twonly/src/utils/json.dart'; +part 'user_data.g.dart'; @JsonSerializable() class UserData { diff --git a/lib/src/model/user_data_json.g.dart b/lib/src/model/json/user_data.g.dart similarity index 95% rename from lib/src/model/user_data_json.g.dart rename to lib/src/model/json/user_data.g.dart index ef2cd1d..d8217b4 100644 --- a/lib/src/model/user_data_json.g.dart +++ b/lib/src/model/json/user_data.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'user_data_json.dart'; +part of 'user_data.dart'; // ************************************************************************** // JsonSerializableGenerator diff --git a/lib/src/providers/api_provider.dart b/lib/src/providers/api_provider.dart index 965c1b1..d05da02 100644 --- a/lib/src/providers/api_provider.dart +++ b/lib/src/providers/api_provider.dart @@ -3,17 +3,18 @@ import 'dart:math'; import 'package:fixnum/fixnum.dart'; import 'package:flutter/material.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; - import 'package:logging/logging.dart'; import 'package:twonly/src/proto/api/client_to_server.pb.dart' as client; import 'package:twonly/src/proto/api/client_to_server.pbserver.dart'; import 'package:twonly/src/proto/api/error.pb.dart'; import 'package:twonly/src/proto/api/server_to_client.pb.dart' as server; -import 'package:twonly/src/signal/signal_helper.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/storage.dart'; +// ignore: library_prefixes +import 'package:twonly/src/utils/signal.dart' as SignalHelper; import 'package:web_socket_channel/io.dart'; +// ignore: implementation_imports import 'package:libsignal_protocol_dart/src/ecc/ed25519.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; diff --git a/lib/src/signal/signal_helper.dart b/lib/src/signal/signal_helper.dart index 10ae58d..bee189f 100644 --- a/lib/src/signal/signal_helper.dart +++ b/lib/src/signal/signal_helper.dart @@ -1,13 +1,8 @@ import 'dart:convert'; import 'dart:developer'; import 'dart:typed_data'; -import 'package:fixnum/fixnum.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; -import 'package:logging/logging.dart'; -import 'package:twonly/src/model/signal_identity_json.dart'; -import 'package:twonly/src/proto/api/server_to_client.pb.dart'; -import 'package:twonly/src/utils/misc.dart'; - +import 'package:twonly/src/utils/signal.dart'; import 'connect_sender_key_store.dart'; import 'connect_signal_protocol_store.dart'; @@ -23,8 +18,8 @@ class SignalDataModel { // Session validation Future generateSessionFingerPrint(String target) async { try { - IdentityKey? targetIdentity = await signalStore.getIdentity( - SignalProtocolAddress(target, SignalHelper.defaultDeviceId)); + IdentityKey? targetIdentity = await signalStore + .getIdentity(SignalProtocolAddress(target, defaultDeviceId)); if (targetIdentity != null) { final generator = NumericFingerprintGenerator(5200); final localFingerprint = generator.createFor( @@ -48,8 +43,8 @@ class SignalDataModel { Future getEncryptedText(String text, String target) async { try { - SessionCipher session = SessionCipher.fromStore(signalStore, - SignalProtocolAddress(target, SignalHelper.defaultDeviceId)); + SessionCipher session = SessionCipher.fromStore( + signalStore, SignalProtocolAddress(target, defaultDeviceId)); final ciphertext = await session.encrypt(Uint8List.fromList(utf8.encode(text))); Map data = { @@ -65,8 +60,8 @@ class SignalDataModel { Future getDecryptedText(String source, String msg) async { try { - SessionCipher session = SessionCipher.fromStore(signalStore, - SignalProtocolAddress(source, SignalHelper.defaultDeviceId)); + SessionCipher session = SessionCipher.fromStore( + signalStore, SignalProtocolAddress(source, defaultDeviceId)); Map data = jsonDecode(msg); if (data["type"] == CiphertextMessage.prekeyType) { PreKeySignalMessage pre = @@ -89,156 +84,3 @@ class SignalDataModel { } } } - -int userIdToRegistrationId(List userId) { - int result = 0; - for (int i = 8; i < 16; i++) { - result = (result << 8) | userId[i]; - } - return result; -} - -String uint8ListToHex(List list) { - final StringBuffer hexBuffer = StringBuffer(); - for (int byte in list) { - hexBuffer.write(byte.toRadixString(16).padLeft(2, '0')); - } - return hexBuffer.toString().toUpperCase(); -} - -class SignalHelper { - static const int defaultDeviceId = 1; - - static Future getPrivateKey() async { - final signalIdentity = await getSignalIdentity(); - if (signalIdentity == null) { - return null; - } - - final IdentityKeyPair identityKeyPair = - IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List); - - return identityKeyPair.getPrivateKey(); - } - - static Future addNewContact(Response_UserData userData) async { - final Int64 userId = userData.userId; - - SignalProtocolAddress targetAddress = - SignalProtocolAddress(userId.toString(), SignalHelper.defaultDeviceId); - - SignalProtocolStore? signalStore = await SignalHelper.getSignalStore(); - if (signalStore == null) { - return false; - } - - SessionBuilder sessionBuilder = - SessionBuilder.fromSignalStore(signalStore, targetAddress); - - ECPublicKey? tempPrePublicKey; - int? tempPreKeyId; - if (userData.prekeys.isNotEmpty) { - tempPrePublicKey = Curve.decodePoint( - DjbECPublicKey(Uint8List.fromList(userData.prekeys.first.prekey)) - .serialize(), - 1); - tempPreKeyId = userData.prekeys.first.id.toInt(); - } - // Signed pre key calculation - int tempSignedPreKeyId = userData.signedPrekeyId.toInt(); - // Map? tempSignedPreKey = remoteBundle["signedPreKey"]; - ECPublicKey? tempSignedPreKeyPublic; - Uint8List? tempSignedPreKeySignature; - // if (tempSignedPreKey != null) { - tempSignedPreKeyPublic = Curve.decodePoint( - DjbECPublicKey(Uint8List.fromList(userData.signedPrekey)).serialize(), - 1); - tempSignedPreKeySignature = - Uint8List.fromList(userData.signedPrekeySignature); - // } - // Identity key calculation - IdentityKey tempIdentityKey = IdentityKey(Curve.decodePoint( - DjbECPublicKey(Uint8List.fromList(userData.publicIdentityKey)) - .serialize(), - 1)); - PreKeyBundle preKeyBundle = PreKeyBundle( - userData.userId.toInt(), - 1, - tempPreKeyId, - tempPrePublicKey, - tempSignedPreKeyId, - tempSignedPreKeyPublic, - tempSignedPreKeySignature, - tempIdentityKey, - ); - - try { - await sessionBuilder.processPreKeyBundle(preKeyBundle); - return true; - } catch (e) { - Logger("signal_helper").shout("Error: $e"); - return false; - } - } - - static Future getSignalStore() async { - return await getSignalStoreFromIdentity((await getSignalIdentity())!); - } - - static Future getSignalIdentity() async { - final storage = getSecureStorage(); - final signalIdentityJson = await storage.read(key: "signal_identity"); - if (signalIdentityJson == null) { - return null; - } - - return SignalIdentity.fromJson(jsonDecode(signalIdentityJson)); - } - - static Future getSignalStoreFromIdentity( - SignalIdentity signalIdentity) async { - final IdentityKeyPair identityKeyPair = - IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List); - - return ConnectSignalProtocolStore( - identityKeyPair, signalIdentity.registrationId.toInt()); - } - - static Future> getPreKeys() async { - final preKeys = generatePreKeys(0, 200); - final signalStore = await getSignalStore(); - if (signalStore == null) return []; - for (final p in preKeys) { - await signalStore.preKeyStore.storePreKey(p.id, p); - } - return preKeys; - } - - static Future createIfNotExistsSignalIdentity() async { - final storage = getSecureStorage(); - - final signalIdentity = await storage.read(key: "signal_identity"); - if (signalIdentity != null) { - return; - } - - final identityKeyPair = generateIdentityKeyPair(); - final registrationId = generateRegistrationId(true); - - ConnectSignalProtocolStore signalStore = - ConnectSignalProtocolStore(identityKeyPair, registrationId); - - final signedPreKey = - generateSignedPreKey(identityKeyPair, SignalHelper.defaultDeviceId); - - await signalStore.signedPreKeyStore - .storeSignedPreKey(signedPreKey.id, signedPreKey); - - final storedSignalIdentity = SignalIdentity( - identityKeyPairU8List: identityKeyPair.serialize(), - registrationId: Int64(registrationId)); - - await storage.write( - key: "signal_identity", value: jsonEncode(storedSignalIdentity)); - } -} diff --git a/lib/src/utils/api.dart b/lib/src/utils/api.dart index 479b12c..28a9671 100644 --- a/lib/src/utils/api.dart +++ b/lib/src/utils/api.dart @@ -2,10 +2,11 @@ import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:twonly/main.dart'; import 'package:twonly/src/model/contacts_model.dart'; -import 'package:twonly/src/signal/signal_helper.dart'; import 'package:twonly/src/providers/api_provider.dart'; import 'package:twonly/src/utils/misc.dart'; -import 'package:twonly/src/model/user_data_json.dart'; +// ignore: library_prefixes +import 'package:twonly/src/utils/signal.dart' as SignalHelper; +import 'package:twonly/src/model/json/user_data.dart'; Future addNewContact(String username) async { final res = await apiProvider.getUserData(username); diff --git a/lib/src/utils/json.dart b/lib/src/utils/json.dart new file mode 100644 index 0000000..70d0e8e --- /dev/null +++ b/lib/src/utils/json.dart @@ -0,0 +1,31 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:fixnum/fixnum.dart'; +import 'dart:convert'; +import 'dart:typed_data'; + +class Int64Converter implements JsonConverter { + const Int64Converter(); + + @override + Int64 fromJson(String json) { + return Int64.parseInt(json); + } + + @override + String toJson(Int64 object) { + return object.toString(); + } +} + +class Uint8ListConverter implements JsonConverter { + const Uint8ListConverter(); + @override + Uint8List fromJson(String json) { + return base64Decode(json); + } + + @override + String toJson(Uint8List object) { + return base64Encode(object); + } +} diff --git a/lib/src/utils/signal.dart b/lib/src/utils/signal.dart new file mode 100644 index 0000000..414a97e --- /dev/null +++ b/lib/src/utils/signal.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:fixnum/fixnum.dart'; +import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; +import 'package:logging/logging.dart'; +import 'package:twonly/src/model/json/signal_identity.dart'; +import 'package:twonly/src/proto/api/server_to_client.pb.dart'; +import 'package:twonly/src/signal/connect_signal_protocol_store.dart'; +import 'package:twonly/src/utils/misc.dart'; + +const int defaultDeviceId = 1; + +Future getPrivateKey() async { + final signalIdentity = await getSignalIdentity(); + if (signalIdentity == null) { + return null; + } + + final IdentityKeyPair identityKeyPair = + IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List); + + return identityKeyPair.getPrivateKey(); +} + +Future addNewContact(Response_UserData userData) async { + final Int64 userId = userData.userId; + + SignalProtocolAddress targetAddress = + SignalProtocolAddress(userId.toString(), defaultDeviceId); + + SignalProtocolStore? signalStore = await getSignalStore(); + if (signalStore == null) { + return false; + } + + SessionBuilder sessionBuilder = + SessionBuilder.fromSignalStore(signalStore, targetAddress); + + ECPublicKey? tempPrePublicKey; + int? tempPreKeyId; + if (userData.prekeys.isNotEmpty) { + tempPrePublicKey = Curve.decodePoint( + DjbECPublicKey(Uint8List.fromList(userData.prekeys.first.prekey)) + .serialize(), + 1); + tempPreKeyId = userData.prekeys.first.id.toInt(); + } + // Signed pre key calculation + int tempSignedPreKeyId = userData.signedPrekeyId.toInt(); + // Map? tempSignedPreKey = remoteBundle["signedPreKey"]; + ECPublicKey? tempSignedPreKeyPublic; + Uint8List? tempSignedPreKeySignature; + // if (tempSignedPreKey != null) { + tempSignedPreKeyPublic = Curve.decodePoint( + DjbECPublicKey(Uint8List.fromList(userData.signedPrekey)).serialize(), 1); + tempSignedPreKeySignature = + Uint8List.fromList(userData.signedPrekeySignature); + // } + // Identity key calculation + IdentityKey tempIdentityKey = IdentityKey(Curve.decodePoint( + DjbECPublicKey(Uint8List.fromList(userData.publicIdentityKey)) + .serialize(), + 1)); + PreKeyBundle preKeyBundle = PreKeyBundle( + userData.userId.toInt(), + 1, + tempPreKeyId, + tempPrePublicKey, + tempSignedPreKeyId, + tempSignedPreKeyPublic, + tempSignedPreKeySignature, + tempIdentityKey, + ); + + try { + await sessionBuilder.processPreKeyBundle(preKeyBundle); + return true; + } catch (e) { + Logger("signal_helper").shout("Error: $e"); + return false; + } +} + +Future getSignalStore() async { + return await getSignalStoreFromIdentity((await getSignalIdentity())!); +} + +Future getSignalIdentity() async { + final storage = getSecureStorage(); + final signalIdentityJson = await storage.read(key: "signal_identity"); + if (signalIdentityJson == null) { + return null; + } + + return SignalIdentity.fromJson(jsonDecode(signalIdentityJson)); +} + +Future getSignalStoreFromIdentity( + SignalIdentity signalIdentity) async { + final IdentityKeyPair identityKeyPair = + IdentityKeyPair.fromSerialized(signalIdentity.identityKeyPairU8List); + + return ConnectSignalProtocolStore( + identityKeyPair, signalIdentity.registrationId.toInt()); +} + +Future> getPreKeys() async { + final preKeys = generatePreKeys(0, 200); + final signalStore = await getSignalStore(); + if (signalStore == null) return []; + for (final p in preKeys) { + await signalStore.preKeyStore.storePreKey(p.id, p); + } + return preKeys; +} + +Future createIfNotExistsSignalIdentity() async { + final storage = getSecureStorage(); + + final signalIdentity = await storage.read(key: "signal_identity"); + if (signalIdentity != null) { + return; + } + + final identityKeyPair = generateIdentityKeyPair(); + final registrationId = generateRegistrationId(true); + + ConnectSignalProtocolStore signalStore = + ConnectSignalProtocolStore(identityKeyPair, registrationId); + + final signedPreKey = generateSignedPreKey(identityKeyPair, defaultDeviceId); + + await signalStore.signedPreKeyStore + .storeSignedPreKey(signedPreKey.id, signedPreKey); + + final storedSignalIdentity = SignalIdentity( + identityKeyPairU8List: identityKeyPair.serialize(), + registrationId: Int64(registrationId)); + + await storage.write( + key: "signal_identity", value: jsonEncode(storedSignalIdentity)); +} diff --git a/lib/src/utils/storage.dart b/lib/src/utils/storage.dart index eaf3c15..9ccc641 100644 --- a/lib/src/utils/storage.dart +++ b/lib/src/utils/storage.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:twonly/main.dart'; -import 'package:twonly/src/model/user_data_json.dart'; +import 'package:twonly/src/model/json/user_data.dart'; import 'package:twonly/src/utils/misc.dart'; Future isUserCreated() async { diff --git a/lib/src/views/profile_view.dart b/lib/src/views/profile_view.dart index 5c9659f..c452df1 100644 --- a/lib/src/views/profile_view.dart +++ b/lib/src/views/profile_view.dart @@ -1,4 +1,4 @@ -import 'package:twonly/src/model/user_data_json.dart'; +import 'package:twonly/src/model/json/user_data.dart'; import 'package:restart_app/restart_app.dart'; import 'package:flutter/material.dart'; import 'package:twonly/src/settings/settings_controller.dart';