Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • DanBaDo/ginkgo
  • flodef/ginkgo
  • zicmama/ginkgo
  • vjrj/ginkgo
  • pokapow/ginkgo
  • weblate/ginkgo
6 results
Show changes
Showing
with 1187 additions and 91 deletions
debian/gui/g1nkgo.png

11.9 KiB

#!/bin/sh
#######################################################
#
# Add here the commands to be excuted before the package
# has been installed
#
set -e
#DEBHELPER#
echo Installing g1nkgo
# Create some similar file to this and name them .env and .env.dev
CURRENCY=g1
SENTRY_DSN=https://306345cb87ee4e1cbbe9023fb4afc5fc@sentry.comunes.org/6
# Nodes space-separated
#
# v1
# The duniter nodes are only used at boot time, later it tries to calculate periodically the nodes
# that are available with the less latency
DUNITER_NODES=https://g1.duniter.org https://g1.le-sou.org https://g1.cgeek.fr https://g1.monnaielibreoccitanie.org https://g1.duniter.fr https://g1.le-sou.org https://g1.cgeek.fr
CESIUM_PLUS_NODES=https://g1.data.le-sou.org https://g1.data.e-is.pro https://g1.data.presles.fr https://g1.data.mithril.re https://g1.data.brussels.ovh https://g1.data.pini.fr
GVA_NODES=https://g1v1.p2p.legal/gva https://g1.asycn.io/gva https://duniter.pini.fr/gva https://duniter-v1.comunes.net/gva
#
# v2
ENDPOINTS=wss://gdev.cgeek.fr/ws wss://gdev.trentesaux.fr/ws wss://gdev.gyroi.de/ws wss://gdev-smith.pini.fr/ws wss://gdev.pini.fr/ws wss://gdev.txmn.tk/ws wss://duniter-v2-vjrj-gdev.comunes.net/ws wss://bulmagdev.sleoconnect.fr/ws wss://gdev.cuates.net/ws wss://gdev.matograine.fr/ws wss://gdev.p2p.legal/ws
DUNITER_INDEXER_NODES=https://squid.gdev.coinduf.eu/v1/graphql https://squid.gdev.gyroi.de/v1/graphql https://duniter-v2-vjrj-squid.comunes.net/v1/graphql
DATAPOD_ENDPOINTS=https://datapod.gyroi.de/v1/graphql https://datapod.coinduf.eu/v1/graphql
IPFS_GATEWAYS=https://gyroi.de https://gateway.datapod.coinduf.eu/
GITLAB_TOKEN=something
......@@ -468,4 +468,9 @@
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
SystemCapabilities = {
com.apple.BackgroundModes = {
enabled = 1;
};
};
}
......@@ -45,6 +45,7 @@
<array>
<string>ast</string>
<string>en</string>
<string>eo</string>
<string>es</string>
<string>eu</string>
<string>fr</string>
......@@ -66,5 +67,20 @@
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera permission is required for barcode scanning.</string>
<key>UIBackgroundModes</key>
<array>
<string>processing</string>
</array>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>org.comunes.ginkgo.fetchWalletsTransactionsTask</string>
</array>
<!-- PermissionType.mediaLibrary -->
<key>NSAppleMusicUsageDescription</key>
<string>description</string>
<key>kTCCServiceMediaLibrary</key>
<string>description</string>
<key>FlutterDeepLinkingEnabled</key>
<false/>
</dict>
</plist>
......@@ -10,6 +10,14 @@ class AppBlocObserver extends BlocObserver {
logger('============= onCreate ============= ${bloc.runtimeType}');
}
@override
void onClose(BlocBase<dynamic> bloc) {
logger('============= onClose ============= ${bloc.runtimeType}');
// final StackTrace stackTrace = StackTrace.current;
// logger(stackTrace.toString());
super.onClose(bloc);
}
@override
void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
super.onChange(bloc, change);
......
import 'package:flutter/material.dart';
const ColorScheme lightColorScheme = ColorScheme(
brightness: Brightness.light,
primary: Color(0xFF526600),
onPrimary: Color(0xFFFFFFFF),
primaryContainer: Color(0xFFD4ED7F),
onPrimaryContainer: Color(0xFF171E00),
secondary: Color(0xFF5B6146),
onSecondary: Color(0xFFFFFFFF),
secondaryContainer: Color(0xFFE0E6C4),
onSecondaryContainer: Color(0xFF191E08),
tertiary: Color(0xFF516600),
onTertiary: Color(0xFFFFFFFF),
tertiaryContainer: Color(0xFFC7F333),
onTertiaryContainer: Color(0xFF161E00),
error: Color(0xFFBA1A1A),
errorContainer: Color(0xFFFFDAD6),
onError: Color(0xFFFFFFFF),
onErrorContainer: Color(0xFF410002),
background: Color(0xFFFEFCF4),
onBackground: Color(0xFF1B1C17),
surface: Color(0xFFFEFCF4),
onSurface: Color(0xFF1B1C17),
surfaceVariant: Color(0xFFE3E4D3),
onSurfaceVariant: Color(0xFF46483C),
outline: Color(0xFF77786B),
onInverseSurface: Color(0xFFF3F1E9),
inverseSurface: Color(0xFF30312B),
inversePrimary: Color(0xFFB8D166),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFF526600),
outlineVariant: Color(0xFFC7C8B8),
scrim: Color(0xFF000000),
);
const ColorScheme darkColorScheme = ColorScheme(
brightness: Brightness.dark,
primary: Color(0xFFB8D166),
onPrimary: Color(0xFF293500),
primaryContainer: Color(0xFF3D4D00),
onPrimaryContainer: Color(0xFFD4ED7F),
secondary: Color(0xFFC4CAA9),
onSecondary: Color(0xFF2D331B),
secondaryContainer: Color(0xFF444930),
onSecondaryContainer: Color(0xFFE0E6C4),
tertiary: Color(0xFFACD605),
onTertiary: Color(0xFF283500),
tertiaryContainer: Color(0xFF3C4D00),
onTertiaryContainer: Color(0xFFC7F333),
error: Color(0xFFFFB4AB),
errorContainer: Color(0xFF93000A),
onError: Color(0xFF690005),
onErrorContainer: Color(0xFFFFDAD6),
background: Color(0xFF1B1C17),
onBackground: Color(0xFFE4E3DA),
surface: Color(0xFF1B1C17),
onSurface: Color(0xFFE4E3DA),
surfaceVariant: Color(0xFF46483C),
onSurfaceVariant: Color(0xFFC7C8B8),
outline: Color(0xFF909283),
onInverseSurface: Color(0xFF1B1C17),
inverseSurface: Color(0xFFE4E3DA),
inversePrimary: Color(0xFF526600),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFFB8D166),
outlineVariant: Color(0xFF46483C),
scrim: Color(0xFF000000),
);
import 'package:flutter/material.dart';
class CustomBanner extends StatelessWidget {
const CustomBanner({
super.key,
required this.child,
required this.message,
this.color = Colors.red,
this.location = BannerLocation.topEnd,
});
final Widget child;
final String message;
final Color color;
final BannerLocation location;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
child,
CustomPaint(
painter: BannerPainter(
textDirection: Directionality.of(context),
layoutDirection: Directionality.of(context),
location: BannerLocation.bottomEnd,
color: color,
textStyle: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 12.0,
),
message: message,
),
child: Container(),
),
],
);
}
}
import 'package:timeago/timeago.dart';
/// Esperanto Messages
class EoMessages implements LookupMessages {
@override
String prefixAgo() => 'antaŭ';
@override
String prefixFromNow() => 'post';
@override
String suffixAgo() => '';
@override
String suffixFromNow() => '';
@override
String lessThanOneMinute(int seconds) => 'momento';
@override
String aboutAMinute(int minutes) => 'unu minuto';
@override
String minutes(int minutes) => '$minutes minutoj';
@override
String aboutAnHour(int minutes) => 'unu horo';
@override
String hours(int hours) => '$hours horoj';
@override
String aDay(int hours) => 'unu tago';
@override
String days(int days) => '$days tagoj';
@override
String aboutAMonth(int days) => 'unu monato';
@override
String months(int months) => '$months monatoj';
@override
String aboutAYear(int year) => 'unu jaro';
@override
String years(int years) => '$years jaroj';
@override
String wordSeparator() => ' ';
}
/// Esperanto short Messages
class EoShortMessages implements LookupMessages {
@override
String prefixAgo() => '';
@override
String prefixFromNow() => '';
@override
String suffixAgo() => '';
@override
String suffixFromNow() => '';
@override
String lessThanOneMinute(int seconds) => 'nun';
@override
String aboutAMinute(int minutes) => '1 min';
@override
String minutes(int minutes) => '$minutes min';
@override
String aboutAnHour(int minutes) => '~1 hr';
@override
String hours(int hours) => '$hours hr';
@override
String aDay(int hours) => '~1 tago';
@override
String days(int days) => '$days tagoj';
@override
String aboutAMonth(int days) => '~1 mon';
@override
String months(int months) => '$months mon';
@override
String aboutAYear(int year) => '~1 jar';
@override
String years(int years) => '$years jar';
@override
String wordSeparator() => ' ';
}
import 'package:timeago/timeago.dart';
/// Euskara Messages
class EuMessages implements LookupMessages {
@override
String prefixAgo() => 'duela';
@override
String prefixFromNow() => 'hemendik';
@override
String suffixAgo() => '';
@override
String suffixFromNow() => 'ra';
@override
String lessThanOneMinute(int seconds) => 'momentu bat';
@override
String aboutAMinute(int minutes) => 'minutu bat';
@override
String minutes(int minutes) => '$minutes minutu';
@override
String aboutAnHour(int minutes) => 'ordu bat';
@override
String hours(int hours) => '$hours ordu';
@override
String aDay(int hours) => 'egun bat';
@override
String days(int days) => '$days egun';
@override
String aboutAMonth(int days) => 'hilabete bat';
@override
String months(int months) => '$months hilabete';
@override
String aboutAYear(int year) => 'urte bat';
@override
String years(int years) => '$years urte';
@override
String wordSeparator() => ' ';
}
/// Euskara short Messages
class EuShortMessages implements LookupMessages {
@override
String prefixAgo() => 'd.';
@override
String prefixFromNow() => 'h.';
@override
String suffixAgo() => '';
@override
String suffixFromNow() => 'r.';
@override
String lessThanOneMinute(int seconds) => 'orain';
@override
String aboutAMinute(int minutes) => '1 min';
@override
String minutes(int minutes) => '$minutes min';
@override
String aboutAnHour(int minutes) => '~1 ord.';
@override
String hours(int hours) => '$hours ord.';
@override
String aDay(int hours) => '~1 eg.';
@override
String days(int days) => '$days eg.';
@override
String aboutAMonth(int days) => '~1 hil.';
@override
String months(int months) => '$months hil.';
@override
String aboutAYear(int year) => '~1 urt.';
@override
String years(int years) => '$years urt.';
@override
String wordSeparator() => ' ';
}
import 'package:timeago/timeago.dart';
/// Galego Messages
class GlMessages implements LookupMessages {
@override
String prefixAgo() => 'hai';
@override
String prefixFromNow() => 'dentro de';
@override
String suffixAgo() => '';
@override
String suffixFromNow() => '';
@override
String lessThanOneMinute(int seconds) => 'un momento';
@override
String aboutAMinute(int minutes) => 'un minuto';
@override
String minutes(int minutes) => '$minutes minutos';
@override
String aboutAnHour(int minutes) => 'unha hora';
@override
String hours(int hours) => '$hours horas';
@override
String aDay(int hours) => 'un día';
@override
String days(int days) => '$days días';
@override
String aboutAMonth(int days) => 'un mes';
@override
String months(int months) => '$months meses';
@override
String aboutAYear(int year) => 'un ano';
@override
String years(int years) => '$years anos';
@override
String wordSeparator() => ' ';
}
/// Galego short Messages
class GlShortMessages implements LookupMessages {
@override
String prefixAgo() => '';
@override
String prefixFromNow() => '';
@override
String suffixAgo() => '';
@override
String suffixFromNow() => '';
@override
String lessThanOneMinute(int seconds) => 'agora';
@override
String aboutAMinute(int minutes) => '1 min';
@override
String minutes(int minutes) => '$minutes min';
@override
String aboutAnHour(int minutes) => '~1 hr';
@override
String hours(int hours) => '$hours hr';
@override
String aDay(int hours) => '~1 día';
@override
String days(int days) => '$days días';
@override
String aboutAMonth(int days) => '~1 mes';
@override
String months(int months) => '$months meses';
@override
String aboutAYear(int year) => '~1 ano';
@override
String years(int years) => '$years anos';
@override
String wordSeparator() => ' ';
}
......@@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import '../../g1/currency.dart';
import '../../g1/distance_precompute.dart';
import 'app_state.dart';
class AppCubit extends HydratedCubit<AppState> {
......@@ -12,6 +13,8 @@ class AppCubit extends HydratedCubit<AppState> {
bool get isIntroViewed => state.introViewed;
bool get isWalletCreatedViewed => state.walletCreatedViewed;
bool get isWarningViewed => state.warningViewed;
bool get isWarningBrowserViewed => state.warningBrowserViewed;
......@@ -26,6 +29,10 @@ class AppCubit extends HydratedCubit<AppState> {
emit(state.copyWith(introViewed: true));
}
void walletCreatedViewed() {
emit(state.copyWith(walletCreatedViewed: true));
}
void warningViewed() {
emit(state.copyWith(warningViewed: true));
}
......@@ -48,9 +55,10 @@ class AppCubit extends HydratedCubit<AppState> {
emit(state.copyWith(expertMode: value));
}
void onFinishTutorial(String tutorialId) {
bool onFinishTutorial(String tutorialId) {
state.tutorials[tutorialId] = true;
emit(state.copyWith(tutorials: state.tutorials));
return true;
}
bool wasTutorialShown(String tutorialId) {
......@@ -68,4 +76,16 @@ class AppCubit extends HydratedCubit<AppState> {
void setUd(double currentUd) {
emit(state.copyWith(currentUd: currentUd));
}
void setV2Mode(bool v2mode) {
emit(state.copyWith(v2mode: v2mode));
}
bool get isV2 => state.v2mode;
void setDistancePreCompute(DistancePrecompute distancePrecompute) {
emit(state.copyWith(distancePrecompute: distancePrecompute));
}
DistancePrecompute? get distancePrecompute => state.distancePrecompute;
}
......@@ -2,6 +2,7 @@ import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import '../../g1/currency.dart';
import '../../g1/distance_precompute.dart';
import 'is_json_serializable.dart';
part 'app_state.g.dart';
......@@ -13,23 +14,31 @@ class AppState extends Equatable implements IsJsonSerializable<AppState> {
this.warningViewed = false,
this.warningBrowserViewed = false,
this.expertMode = false,
bool? walletCreatedViewed,
this.v2mode = false,
Currency? currency,
double? currentUd,
Map<String, bool>? tutorials})
Map<String, bool>? tutorials,
this.distancePrecompute})
: tutorials = tutorials ?? <String, bool>{},
currency = currency ?? Currency.G1,
currentUd = currentUd ?? 10.68; // as 14/05/2023
walletCreatedViewed = walletCreatedViewed ?? introViewed,
currentUd = currentUd ?? 11.06;
factory AppState.fromJson(Map<String, dynamic> json) =>
_$AppStateFromJson(json);
final bool introViewed;
final bool walletCreatedViewed;
final bool warningViewed;
final bool warningBrowserViewed;
final bool expertMode;
final bool v2mode;
final Currency currency;
final double currentUd;
final Map<String, bool> tutorials;
@JsonKey(includeIfNull: false)
final DistancePrecompute? distancePrecompute;
AppState copyWith(
{bool? introViewed,
......@@ -38,31 +47,40 @@ class AppState extends Equatable implements IsJsonSerializable<AppState> {
bool? expertMode,
Currency? currency,
double? currentUd,
Map<String, bool>? tutorials}) {
bool? walletCreatedViewed,
bool? v2mode,
Map<String, bool>? tutorials,
DistancePrecompute? distancePrecompute}) {
return AppState(
introViewed: introViewed ?? this.introViewed,
warningViewed: warningViewed ?? this.warningViewed,
warningBrowserViewed: warningBrowserViewed ?? this.warningBrowserViewed,
expertMode: expertMode ?? this.expertMode,
currency: currency ?? this.currency,
walletCreatedViewed: walletCreatedViewed ?? this.walletCreatedViewed,
v2mode: v2mode ?? this.v2mode,
currentUd: currentUd ?? this.currentUd,
tutorials: tutorials ?? this.tutorials);
tutorials: tutorials ?? this.tutorials,
distancePrecompute: distancePrecompute ?? this.distancePrecompute);
}
@override
AppState fromJson(Map<String, dynamic> json) => AppState.fromJson(json);
AppState fromJson(Map<String, dynamic> json) => _$AppStateFromJson(json);
@override
Map<String, dynamic> toJson() => _$AppStateToJson(this);
@override
List<Object?> get props => <Object>[
List<Object?> get props => <Object?>[
introViewed,
warningViewed,
expertMode,
warningBrowserViewed,
walletCreatedViewed,
tutorials,
currency,
currentUd
currentUd,
v2mode,
distancePrecompute
];
}
......@@ -11,21 +11,31 @@ AppState _$AppStateFromJson(Map<String, dynamic> json) => AppState(
warningViewed: json['warningViewed'] as bool? ?? false,
warningBrowserViewed: json['warningBrowserViewed'] as bool? ?? false,
expertMode: json['expertMode'] as bool? ?? false,
walletCreatedViewed: json['walletCreatedViewed'] as bool?,
v2mode: json['v2mode'] as bool? ?? false,
currency: $enumDecodeNullable(_$CurrencyEnumMap, json['currency']),
currentUd: (json['currentUd'] as num?)?.toDouble(),
tutorials: (json['tutorials'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(k, e as bool),
),
distancePrecompute: json['distancePrecompute'] == null
? null
: DistancePrecompute.fromJson(
json['distancePrecompute'] as Map<String, dynamic>),
);
Map<String, dynamic> _$AppStateToJson(AppState instance) => <String, dynamic>{
'introViewed': instance.introViewed,
'walletCreatedViewed': instance.walletCreatedViewed,
'warningViewed': instance.warningViewed,
'warningBrowserViewed': instance.warningBrowserViewed,
'expertMode': instance.expertMode,
'v2mode': instance.v2mode,
'currency': _$CurrencyEnumMap[instance.currency]!,
'currentUd': instance.currentUd,
'tutorials': instance.tutorials,
if (instance.distancePrecompute case final value?)
'distancePrecompute': value,
};
const _$CurrencyEnumMap = {
......
import 'package:durt/durt.dart';
import 'package:polkadart_keyring/polkadart_keyring.dart';
class AuthDataV1 {
AuthDataV1(this.password, this.salt);
String password;
String salt;
}
class AuthDataV2 {
AuthDataV2(this.mnemonic, this.meta);
String mnemonic;
String meta;
}
class AuthData {
AuthData({this.v1, this.v2});
AuthDataV1? v1;
AuthDataV2? v2;
}
Future<KeyPair> createPair(AuthData data, Keyring keyring) async {
if (data.v1 != null) {
final CesiumWallet wallet = CesiumWallet(data.v1!.salt, data.v1!.password);
final KeyPair keyPair = KeyPair.ed25519.fromSeed(wallet.seed);
return keyPair;
} else if (data.v2 != null) {
final KeyPair keyPair = await keyring.fromUri(data.v2!.mnemonic,
password: data.v2!.meta, keyPairType: KeyPairType.sr25519);
return keyPair;
} else {
throw Exception('Data format not recognized');
}
}
......@@ -9,6 +9,8 @@ class BottomNavCubit extends HydratedCubit<int> {
void updateIndex(int index) => emit(index);
int get currentIndex => state;
void getFirstScreen() => emit(0);
void getSecondScreen() => emit(1);
......
import 'package:copy_with_extension/copy_with_extension.dart';
import 'package:json_annotation/json_annotation.dart';
import 'contact.dart';
part 'cert.g.dart';
@CopyWith()
@JsonSerializable()
class Cert {
Cert({
required this.id,
required this.issuerId,
required this.receiverId,
required this.createdOn,
required this.expireOn,
required this.isActive,
required this.updatedOn,
});
factory Cert.fromJson(Map<String, dynamic> json) => _$CertFromJson(json);
final String id;
final Contact issuerId;
final Contact receiverId;
final int createdOn;
final int expireOn;
final bool isActive;
final int updatedOn;
Map<String, dynamic> toJson() => _$CertToJson(this);
}
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'cert.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class _$CertCWProxy {
Cert id(String id);
Cert issuerId(Contact issuerId);
Cert receiverId(Contact receiverId);
Cert createdOn(int createdOn);
Cert expireOn(int expireOn);
Cert isActive(bool isActive);
Cert updatedOn(int updatedOn);
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Cert(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// Cert(...).copyWith(id: 12, name: "My name")
/// ````
Cert call({
String? id,
Contact? issuerId,
Contact? receiverId,
int? createdOn,
int? expireOn,
bool? isActive,
int? updatedOn,
});
}
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfCert.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfCert.copyWith.fieldName(...)`
class _$CertCWProxyImpl implements _$CertCWProxy {
const _$CertCWProxyImpl(this._value);
final Cert _value;
@override
Cert id(String id) => this(id: id);
@override
Cert issuerId(Contact issuerId) => this(issuerId: issuerId);
@override
Cert receiverId(Contact receiverId) => this(receiverId: receiverId);
@override
Cert createdOn(int createdOn) => this(createdOn: createdOn);
@override
Cert expireOn(int expireOn) => this(expireOn: expireOn);
@override
Cert isActive(bool isActive) => this(isActive: isActive);
@override
Cert updatedOn(int updatedOn) => this(updatedOn: updatedOn);
@override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Cert(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
///
/// Usage
/// ```dart
/// Cert(...).copyWith(id: 12, name: "My name")
/// ````
Cert call({
Object? id = const $CopyWithPlaceholder(),
Object? issuerId = const $CopyWithPlaceholder(),
Object? receiverId = const $CopyWithPlaceholder(),
Object? createdOn = const $CopyWithPlaceholder(),
Object? expireOn = const $CopyWithPlaceholder(),
Object? isActive = const $CopyWithPlaceholder(),
Object? updatedOn = const $CopyWithPlaceholder(),
}) {
return Cert(
id: id == const $CopyWithPlaceholder() || id == null
? _value.id
// ignore: cast_nullable_to_non_nullable
: id as String,
issuerId: issuerId == const $CopyWithPlaceholder() || issuerId == null
? _value.issuerId
// ignore: cast_nullable_to_non_nullable
: issuerId as Contact,
receiverId:
receiverId == const $CopyWithPlaceholder() || receiverId == null
? _value.receiverId
// ignore: cast_nullable_to_non_nullable
: receiverId as Contact,
createdOn: createdOn == const $CopyWithPlaceholder() || createdOn == null
? _value.createdOn
// ignore: cast_nullable_to_non_nullable
: createdOn as int,
expireOn: expireOn == const $CopyWithPlaceholder() || expireOn == null
? _value.expireOn
// ignore: cast_nullable_to_non_nullable
: expireOn as int,
isActive: isActive == const $CopyWithPlaceholder() || isActive == null
? _value.isActive
// ignore: cast_nullable_to_non_nullable
: isActive as bool,
updatedOn: updatedOn == const $CopyWithPlaceholder() || updatedOn == null
? _value.updatedOn
// ignore: cast_nullable_to_non_nullable
: updatedOn as int,
);
}
}
extension $CertCopyWith on Cert {
/// Returns a callable class that can be used as follows: `instanceOfCert.copyWith(...)` or like so:`instanceOfCert.copyWith.fieldName(...)`.
// ignore: library_private_types_in_public_api
_$CertCWProxy get copyWith => _$CertCWProxyImpl(this);
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Cert _$CertFromJson(Map<String, dynamic> json) => Cert(
id: json['id'] as String,
issuerId: Contact.fromJson(json['issuerId'] as Map<String, dynamic>),
receiverId: Contact.fromJson(json['receiverId'] as Map<String, dynamic>),
createdOn: (json['createdOn'] as num).toInt(),
expireOn: (json['expireOn'] as num).toInt(),
isActive: json['isActive'] as bool,
updatedOn: (json['updatedOn'] as num).toInt(),
);
Map<String, dynamic> _$CertToJson(Cert instance) => <String, dynamic>{
'id': instance.id,
'issuerId': instance.issuerId,
'receiverId': instance.receiverId,
'createdOn': instance.createdOn,
'expireOn': instance.expireOn,
'isActive': instance.isActive,
'updatedOn': instance.updatedOn,
};
......@@ -3,8 +3,13 @@ import 'dart:typed_data';
import 'package:copy_with_extension/copy_with_extension.dart';
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:latlong2/latlong.dart';
import '../../g1/g1_helper.dart';
import '../../g1/g1_v2_helper.dart';
import '../../ui/ui_helpers.dart';
import 'cert.dart';
import 'identity_status.dart';
import 'is_json_serializable.dart';
import 'model_utils.dart';
......@@ -13,17 +18,200 @@ part 'contact.g.dart';
@JsonSerializable()
@CopyWith()
class Contact extends Equatable implements IsJsonSerializable<Contact> {
const Contact({
this.nick,
required this.pubKey,
this.avatar,
this.notes,
this.name,
});
Contact(
{this.nick,
required String pubKey,
String? address,
this.avatar,
this.notes,
this.name,
this.avatarCid,
this.description,
this.city,
this.dataCid,
this.geoLoc,
this.indexRequestCid,
this.socials,
this.time,
this.certsIssued,
this.certsReceived,
this.status,
this.isMember,
this.createdOn,
this.index,
this.expireOn})
:
// ensure that Contact does not have v1 checksums
pubKey = extractPublicKey(pubKey),
address = address ?? addressFromV1Pubkey(extractPublicKey(pubKey));
factory Contact.withIdentityFields({
String? nick,
required String pubKey,
String? address,
List<Cert>? certsReceived,
List<Cert>? certsIssued,
IdentityStatus? status,
bool? isMember,
int? createdOn,
int? index,
int? expireOn,
}) {
return Contact(
nick: nick,
pubKey: pubKey,
address: address,
certsReceived: certsReceived,
certsIssued: certsIssued,
status: status,
isMember: isMember,
createdOn: createdOn,
expireOn: expireOn,
index: index,
);
}
factory Contact.fromJson(Map<String, dynamic> json) =>
_$ContactFromJson(json);
const Contact._(
{this.nick,
required this.pubKey,
required this.address,
this.avatar,
this.notes,
this.name,
this.avatarCid,
this.description,
this.city,
this.dataCid,
this.geoLoc,
this.indexRequestCid,
this.socials,
this.time,
this.certsIssued,
this.certsReceived,
this.status,
this.isMember,
this.createdOn,
this.index,
this.expireOn});
factory Contact.withPubKey(
{String? nick,
required String pubKey,
Uint8List? avatar,
String? notes,
String? name,
String? avatarCid,
String? description,
String? city,
String? dataCid,
LatLng? geoLoc,
String? indexRequestCid,
List<Map<String, String>>? socials,
List<Cert>? certsReceived,
List<Cert>? certsIssued,
int? index,
DateTime? time}) {
return Contact._(
nick: nick,
pubKey: extractPublicKey(pubKey),
address: addressFromV1Pubkey(extractPublicKey(pubKey)),
avatar: avatar,
notes: notes,
name: name,
avatarCid: avatarCid,
description: description,
city: city,
dataCid: dataCid,
geoLoc: geoLoc,
indexRequestCid: indexRequestCid,
socials: socials,
time: time,
certsReceived: certsReceived,
certsIssued: certsIssued,
index: index);
}
factory Contact.empty() {
return const Contact._(
name: '',
pubKey: '',
address: '',
);
}
factory Contact.withAddress(
{String? nick,
required String address,
Uint8List? avatar,
String? notes,
String? name,
String? avatarCid,
String? description,
String? city,
String? dataCid,
LatLng? geoLoc,
String? indexRequestCid,
List<Map<String, String>>? socials,
DateTime? time,
List<Cert>? certsReceived,
List<Cert>? certsIssued,
IdentityStatus? status,
bool? isMember,
int? createdOn,
int? expireOn,
int? index}) {
return Contact._(
nick: nick,
pubKey: v1pubkeyFromAddress(address),
address: address,
avatar: avatar,
notes: notes,
name: name,
avatarCid: avatarCid,
description: description,
city: city,
dataCid: dataCid,
geoLoc: geoLoc,
indexRequestCid: indexRequestCid,
socials: socials,
time: time,
certsReceived: certsReceived,
certsIssued: certsIssued,
status: status,
isMember: isMember,
createdOn: createdOn,
expireOn: expireOn,
index: index);
}
final String? nick;
final String pubKey;
final String address;
@JsonKey(fromJson: uIntFromList, toJson: uIntToList)
final Uint8List? avatar;
final String? notes;
final String? name;
final String? avatarCid;
final String? description;
final String? city;
final String? dataCid;
final LatLng? geoLoc;
final String? indexRequestCid;
final List<Map<String, String>>? socials;
final DateTime? time;
// identity fields
final List<Cert>? certsReceived;
final List<Cert>? certsIssued;
final IdentityStatus? status;
final bool? isMember;
final int? createdOn;
final int? expireOn;
final int? index;
Contact merge(Contact c) {
return Contact(
nick: c.nick ?? nick,
......@@ -31,15 +219,37 @@ class Contact extends Equatable implements IsJsonSerializable<Contact> {
avatar: c.avatar ?? avatar,
notes: c.notes ?? notes,
name: c.name ?? name,
avatarCid: c.avatarCid ?? avatarCid,
description: c.description ?? description,
city: c.city ?? city,
dataCid: c.dataCid ?? dataCid,
geoLoc: c.geoLoc ?? geoLoc,
indexRequestCid: c.indexRequestCid ?? indexRequestCid,
socials: c.socials ?? socials,
time: c.time ?? time,
certsIssued: _mergeCertLists(c.certsIssued, certsIssued),
certsReceived: _mergeCertLists(c.certsReceived, certsReceived),
status: c.status ?? status,
isMember: c.isMember ?? isMember,
createdOn: c.createdOn ?? createdOn,
expireOn: c.expireOn ?? expireOn,
index: c.index ?? index,
);
}
final String? nick;
final String pubKey;
@JsonKey(fromJson: uIntFromList, toJson: uIntToList)
final Uint8List? avatar;
final String? notes;
final String? name;
List<Cert>? _mergeCertLists(List<Cert>? listA, List<Cert>? listB) {
if (listA == null && listB == null) {
return null;
}
if (listA == null) {
return listB;
}
if (listB == null) {
return listA;
}
return listB;
}
@override
List<Object?> get props => <dynamic>[
......@@ -49,8 +259,26 @@ class Contact extends Equatable implements IsJsonSerializable<Contact> {
avatar,
notes,
name,
address,
avatarCid,
description,
city,
dataCid,
geoLoc,
indexRequestCid,
socials,
time,
certsIssued,
certsReceived,
certsIssued,
status,
isMember,
createdOn,
expireOn,
index
];
// Only avatar binary
bool get hasAvatar => avatar != null;
@override
......@@ -69,11 +297,38 @@ class Contact extends Equatable implements IsJsonSerializable<Contact> {
}
String get title => name != null && nick != null
? name != nick
? name != nick && name!.toLowerCase() != nick!.toLowerCase()
? '$name ($nick)'
: name! // avoid "nick (nick)" users
: nick ?? name ?? humanizePubKey(pubKey);
String get titleWithoutNick => name ?? humanizePubKey(pubKey);
String? get subtitle =>
(nick != null || name != null) ? humanizePubKey(pubKey) : null;
String? get subtitleV2 =>
(nick != null || name != null) ? humanizeAddress(address) : null;
Contact cloneWithoutAvatar() {
return Contact(
nick: nick,
pubKey: pubKey,
// avatar: null,
notes: notes,
name: name,
avatarCid: avatarCid,
description: description,
city: city,
dataCid: dataCid,
geoLoc: geoLoc,
indexRequestCid: indexRequestCid,
socials: socials,
time: time);
}
bool keyEqual(Contact other) =>
extractPublicKey(pubKey) == extractPublicKey(other.pubKey);
bool get createdOnV2 => createdOn != null && createdOn! > 0;
}
This diff is collapsed.