mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-16 17:27:39 +00:00
Merge remote-tracking branch 'origin_SW/staging' into add_nano
# Conflicts: # lib/models/isar/stack_theme.dart # lib/models/isar/stack_theme.g.dart # lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart # lib/services/coins/firo/firo_wallet.dart # lib/themes/coin_icon_provider.dart # lib/themes/coin_image_provider.dart # lib/utilities/constants.dart # lib/utilities/enums/coin_enum.dart
This commit is contained in:
commit
553e035ca7
128 changed files with 13031 additions and 4258 deletions
Binary file not shown.
Binary file not shown.
83
assets/svg/anonymize.svg
Normal file
83
assets/svg/anonymize.svg
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg18"
|
||||
sodipodi:docname="tx-icon-anonymize.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
<metadata
|
||||
id="metadata22">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2262"
|
||||
inkscape:window-height="1263"
|
||||
id="namedview20"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="-15.813559"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-x="1019"
|
||||
inkscape:window-y="569"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g8" />
|
||||
<g
|
||||
clip-path="url(#clip0_5035_57299)"
|
||||
id="g8">
|
||||
<g
|
||||
clip-path="url(#clip1_5035_57299)"
|
||||
id="g6"
|
||||
transform="matrix(1.6610229,0,0,1.7055051,-7.9831634,-8.2054918)">
|
||||
<path
|
||||
d="m 9.92728,11.6469 c 0.13122,0.5688 -0.49218,1.0145 -0.9871,0.7028 L 8.27572,11.934 6.88393,14.1606 c -0.3645,0.583 0.05479,1.3393 0.74238,1.3393 h 0.87554 c 0.48235,0 0.87446,0.3916 0.87446,0.8739 0,0.4824 -0.39211,0.8764 -0.87446,0.8764 H 7.62904 c -2.06062,0 -3.31679,-2.2651 -2.22769,-4.0141 L 6.79123,11.0098 6.12514,10.5915 C 5.62994,10.2797 5.75627,9.52505 6.32557,9.3938 L 8.8256,8.81548 C 9.06049,8.7649 9.29838,8.90709 9.35307,9.14498 Z M 12.741,7.15873 13.8689,8.96724 13.2058,9.37959 c -0.4966,0.30925 -0.3711,1.06481 0.199,1.19681 l 2.4992,0.5783 c 0.2358,0.0546 0.4712,-0.0926 0.5253,-0.3284 L 17.0046,8.32631 C 17.1356,7.75728 16.5138,7.31322 16.0183,7.62193 L 15.3522,8.03755 14.2257,6.23396 C 13.1981,4.58951 10.8023,4.58841 9.77416,6.23227 L 9.57182,6.55552 C 9.31752,6.96158 9.4433,7.50381 9.84799,7.75865 10.256,8.01456 10.7987,7.89225 11.0541,7.48412 L 11.2576,7.159 c 0.3486,-0.55754 1.1498,-0.53703 1.4834,-2.7e-4 z m 5.857,6.07957 -0.4646,-0.7454 c -0.2553,-0.4096 -0.7946,-0.5348 -1.2042,-0.2791 -0.4085,0.2548 -0.5338,0.797 -0.2784,1.2053 l 0.4646,0.7424 c 0.365,0.5829 -0.0542,1.3398 -0.7421,1.3398 h -2.6247 l 6e-4,-0.7859 c 0,-0.5846 -0.7068,-0.8774 -1.1203,-0.464 l -1.8159,1.8165 c -0.1701,0.1701 -0.1701,0.4487 2e-4,0.6188 l 1.8161,1.8139 c 0.4135,0.4129 1.1198,0.12 1.1198,-0.4643 l -7e-4,-0.7842 h 2.6212 c 2.0616,3e-4 3.3194,-2.2665 2.2284,-4.0138 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#494949" />
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs16">
|
||||
<clipPath
|
||||
id="clip0_5035_57299">
|
||||
<rect
|
||||
width="24"
|
||||
height="24"
|
||||
fill="white"
|
||||
id="rect10" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip1_5035_57299">
|
||||
<rect
|
||||
width="14"
|
||||
height="14"
|
||||
fill="white"
|
||||
transform="translate(5 5)"
|
||||
id="rect13" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -1 +1 @@
|
|||
Subproject commit 81659ce57952c5ab54ffe6bacfbf43da159fff3e
|
||||
Subproject commit 73d257ed2fe5b204cf3589822e226301b187b86d
|
|
@ -41,7 +41,6 @@ class DB {
|
|||
String boxNameUsedSerialsCache({required Coin coin}) =>
|
||||
"${coin.name}_usedSerialsCache";
|
||||
|
||||
Box<dynamic>? _boxAddressBook;
|
||||
Box<String>? _boxDebugInfo;
|
||||
Box<NodeModel>? _boxNodeModels;
|
||||
Box<NodeModel>? _boxPrimaryNodes;
|
||||
|
@ -100,7 +99,6 @@ class DB {
|
|||
_boxPrefs = await Hive.openBox<dynamic>(boxNamePrefs);
|
||||
}
|
||||
|
||||
_boxAddressBook = await Hive.openBox<dynamic>(boxNameAddressBook);
|
||||
_boxDebugInfo = await Hive.openBox<String>(boxNameDebugInfo);
|
||||
|
||||
if (Hive.isBoxOpen(boxNameNodeModels)) {
|
||||
|
|
|
@ -115,8 +115,9 @@ class CachedElectrumX {
|
|||
key: groupId,
|
||||
value: set);
|
||||
Logging.instance.log(
|
||||
"Updated currently anonymity set for ${coin.name} with group ID $groupId",
|
||||
level: LogLevel.Info);
|
||||
"Updated current anonymity set for ${coin.name} with group ID $groupId",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
}
|
||||
|
||||
return set;
|
||||
|
@ -187,16 +188,17 @@ class CachedElectrumX {
|
|||
}
|
||||
}
|
||||
|
||||
Future<List<dynamic>> getUsedCoinSerials({
|
||||
Future<List<String>> getUsedCoinSerials({
|
||||
required Coin coin,
|
||||
int startNumber = 0,
|
||||
}) async {
|
||||
try {
|
||||
List<dynamic>? cachedSerials = DB.instance.get<dynamic>(
|
||||
final _list = DB.instance.get<dynamic>(
|
||||
boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
|
||||
key: "serials") as List?;
|
||||
|
||||
cachedSerials ??= [];
|
||||
List<String> cachedSerials =
|
||||
_list == null ? [] : List<String>.from(_list);
|
||||
|
||||
final startNumber = cachedSerials.length;
|
||||
|
||||
|
@ -210,8 +212,9 @@ class CachedElectrumX {
|
|||
);
|
||||
|
||||
final serials = await client.getUsedCoinSerials(startNumber: startNumber);
|
||||
List newSerials = [];
|
||||
for (var element in (serials["serials"] as List)) {
|
||||
List<String> newSerials = [];
|
||||
|
||||
for (final element in (serials["serials"] as List)) {
|
||||
if (!isHexadecimal(element as String)) {
|
||||
newSerials.add(base64ToHex(element));
|
||||
} else {
|
||||
|
@ -221,9 +224,10 @@ class CachedElectrumX {
|
|||
cachedSerials.addAll(newSerials);
|
||||
|
||||
await DB.instance.put<dynamic>(
|
||||
boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
|
||||
key: "serials",
|
||||
value: cachedSerials);
|
||||
boxName: DB.instance.boxNameUsedSerialsCache(coin: coin),
|
||||
key: "serials",
|
||||
value: cachedSerials,
|
||||
);
|
||||
|
||||
return cachedSerials;
|
||||
} catch (e, s) {
|
||||
|
|
|
@ -70,7 +70,7 @@ final openedFromSWBFileStringStateProvider =
|
|||
// runs the MyApp widget and checks for new users, caching the value in the
|
||||
// miscellaneous box for later use
|
||||
void main() async {
|
||||
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
GoogleFonts.config.allowRuntimeFetching = false;
|
||||
if (Platform.isIOS) {
|
||||
Util.libraryPath = await getLibraryDirectory();
|
||||
|
@ -162,7 +162,7 @@ void main() async {
|
|||
int dbVersion = DB.instance.get<dynamic>(
|
||||
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
|
||||
0;
|
||||
if (dbVersion < Constants.currentHiveDbVersion) {
|
||||
if (dbVersion < Constants.currentDataVersion) {
|
||||
try {
|
||||
await DbVersionMigrator().migrate(
|
||||
dbVersion,
|
||||
|
@ -178,11 +178,10 @@ void main() async {
|
|||
}
|
||||
}
|
||||
|
||||
//Add Themes directory - TODO
|
||||
// await StackFileSystem.applicationThemesDirectory();
|
||||
|
||||
monero.onStartup();
|
||||
wownero.onStartup();
|
||||
if (!Platform.isLinux && !Platform.isWindows) {
|
||||
wownero.onStartup();
|
||||
}
|
||||
|
||||
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||
// overlays: [SystemUiOverlay.bottom]);
|
||||
|
@ -191,33 +190,8 @@ void main() async {
|
|||
await MainDB.instance.initMainDB();
|
||||
ThemeService.instance.init(MainDB.instance);
|
||||
|
||||
// install default themes
|
||||
if (!(await ThemeService.instance.verifyInstalled(themeId: "light"))) {
|
||||
Logging.instance.log(
|
||||
"Installing default light theme...",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
final lightZip = await rootBundle.load("assets/default_themes/light.zip");
|
||||
await ThemeService.instance
|
||||
.install(themeArchiveData: lightZip.buffer.asUint8List());
|
||||
Logging.instance.log(
|
||||
"Installing default light theme... finished",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
}
|
||||
if (!(await ThemeService.instance.verifyInstalled(themeId: "dark"))) {
|
||||
Logging.instance.log(
|
||||
"Installing default dark theme... ",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
final darkZip = await rootBundle.load("assets/default_themes/dark.zip");
|
||||
await ThemeService.instance
|
||||
.install(themeArchiveData: darkZip.buffer.asUint8List());
|
||||
Logging.instance.log(
|
||||
"Installing default dark theme... finished",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
}
|
||||
// check and update or install default themes
|
||||
await ThemeService.instance.checkDefaultThemesOnStartup();
|
||||
|
||||
runApp(const ProviderScope(child: MyApp()));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:convert';
|
|||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
|
||||
class Contact {
|
||||
final String? emojiChar;
|
||||
final String name;
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
|
||||
class ContactAddressEntry {
|
||||
final Coin coin;
|
||||
final String address;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
|
@ -57,7 +57,7 @@ class AddressEntryData extends ChangeNotifier {
|
|||
}
|
||||
|
||||
bool get isValidAddress {
|
||||
if ( coin == null) {
|
||||
if (coin == null) {
|
||||
return true;
|
||||
}
|
||||
if (_address == null) {
|
||||
|
@ -67,8 +67,11 @@ class AddressEntryData extends ChangeNotifier {
|
|||
}
|
||||
|
||||
ContactAddressEntry buildAddressEntry() {
|
||||
return ContactAddressEntry(
|
||||
coin: coin!, address: address!, label: addressLabel!);
|
||||
return ContactAddressEntry()
|
||||
..coinName = coin!.name
|
||||
..address = address!
|
||||
..other = null
|
||||
..label = addressLabel!;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
part 'contact_entry.g.dart';
|
||||
|
||||
|
@ -16,9 +17,92 @@ class ContactEntry {
|
|||
|
||||
late final String? emojiChar;
|
||||
late final String name;
|
||||
late final List<String> addresses;
|
||||
late final List<ContactAddressEntry> addresses;
|
||||
late final bool isFavorite;
|
||||
|
||||
@Index(unique: true, replace: true)
|
||||
late final String customId;
|
||||
}
|
||||
|
||||
ContactEntry copyWith({
|
||||
bool shouldCopyEmojiWithNull = false,
|
||||
String? emojiChar,
|
||||
String? name,
|
||||
List<ContactAddressEntry>? addresses,
|
||||
bool? isFavorite,
|
||||
}) {
|
||||
List<ContactAddressEntry> _addresses = [];
|
||||
if (addresses == null) {
|
||||
for (var e in this.addresses) {
|
||||
_addresses.add(e.copyWith());
|
||||
}
|
||||
} else {
|
||||
for (var e in addresses) {
|
||||
_addresses.add(e.copyWith());
|
||||
}
|
||||
}
|
||||
String? newEmoji;
|
||||
if (shouldCopyEmojiWithNull) {
|
||||
newEmoji = emojiChar;
|
||||
} else {
|
||||
newEmoji = emojiChar ?? this.emojiChar;
|
||||
}
|
||||
|
||||
return ContactEntry(
|
||||
emojiChar: newEmoji,
|
||||
name: name ?? this.name,
|
||||
addresses: _addresses,
|
||||
isFavorite: isFavorite ?? this.isFavorite,
|
||||
customId: customId,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"emoji": emojiChar,
|
||||
"name": name,
|
||||
"addresses": addresses.map((e) => e.toMap()).toList(),
|
||||
"id": customId,
|
||||
"isFavorite": isFavorite,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@embedded
|
||||
class ContactAddressEntry {
|
||||
late final String coinName;
|
||||
late final String address;
|
||||
late final String label;
|
||||
late final String? other;
|
||||
|
||||
@ignore
|
||||
Coin get coin => Coin.values.byName(coinName);
|
||||
|
||||
ContactAddressEntry();
|
||||
|
||||
ContactAddressEntry copyWith({
|
||||
Coin? coin,
|
||||
String? address,
|
||||
String? label,
|
||||
String? other,
|
||||
}) {
|
||||
return ContactAddressEntry()
|
||||
..coinName = coin?.name ?? coinName
|
||||
..address = address ?? this.address
|
||||
..label = label ?? this.label
|
||||
..other = other ?? this.other;
|
||||
}
|
||||
|
||||
Map<String, String> toMap() {
|
||||
return {
|
||||
"label": label,
|
||||
"address": address,
|
||||
"coin": coin.name,
|
||||
"other": other ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "AddressBookEntry: ${toMap()}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ const ContactEntrySchema = CollectionSchema(
|
|||
r'addresses': PropertySchema(
|
||||
id: 0,
|
||||
name: r'addresses',
|
||||
type: IsarType.stringList,
|
||||
type: IsarType.objectList,
|
||||
target: r'ContactAddressEntry',
|
||||
),
|
||||
r'customId': PropertySchema(
|
||||
id: 1,
|
||||
|
@ -64,7 +65,7 @@ const ContactEntrySchema = CollectionSchema(
|
|||
)
|
||||
},
|
||||
links: {},
|
||||
embeddedSchemas: {},
|
||||
embeddedSchemas: {r'ContactAddressEntry': ContactAddressEntrySchema},
|
||||
getId: _contactEntryGetId,
|
||||
getLinks: _contactEntryGetLinks,
|
||||
attach: _contactEntryAttach,
|
||||
|
@ -79,9 +80,11 @@ int _contactEntryEstimateSize(
|
|||
var bytesCount = offsets.last;
|
||||
bytesCount += 3 + object.addresses.length * 3;
|
||||
{
|
||||
final offsets = allOffsets[ContactAddressEntry]!;
|
||||
for (var i = 0; i < object.addresses.length; i++) {
|
||||
final value = object.addresses[i];
|
||||
bytesCount += value.length * 3;
|
||||
bytesCount +=
|
||||
ContactAddressEntrySchema.estimateSize(value, offsets, allOffsets);
|
||||
}
|
||||
}
|
||||
bytesCount += 3 + object.customId.length * 3;
|
||||
|
@ -101,7 +104,12 @@ void _contactEntrySerialize(
|
|||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
writer.writeStringList(offsets[0], object.addresses);
|
||||
writer.writeObjectList<ContactAddressEntry>(
|
||||
offsets[0],
|
||||
allOffsets,
|
||||
ContactAddressEntrySchema.serialize,
|
||||
object.addresses,
|
||||
);
|
||||
writer.writeString(offsets[1], object.customId);
|
||||
writer.writeString(offsets[2], object.emojiChar);
|
||||
writer.writeBool(offsets[3], object.isFavorite);
|
||||
|
@ -115,7 +123,13 @@ ContactEntry _contactEntryDeserialize(
|
|||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
final object = ContactEntry(
|
||||
addresses: reader.readStringList(offsets[0]) ?? [],
|
||||
addresses: reader.readObjectList<ContactAddressEntry>(
|
||||
offsets[0],
|
||||
ContactAddressEntrySchema.deserialize,
|
||||
allOffsets,
|
||||
ContactAddressEntry(),
|
||||
) ??
|
||||
[],
|
||||
customId: reader.readString(offsets[1]),
|
||||
emojiChar: reader.readStringOrNull(offsets[2]),
|
||||
isFavorite: reader.readBool(offsets[3]),
|
||||
|
@ -133,7 +147,13 @@ P _contactEntryDeserializeProp<P>(
|
|||
) {
|
||||
switch (propertyId) {
|
||||
case 0:
|
||||
return (reader.readStringList(offset) ?? []) as P;
|
||||
return (reader.readObjectList<ContactAddressEntry>(
|
||||
offset,
|
||||
ContactAddressEntrySchema.deserialize,
|
||||
allOffsets,
|
||||
ContactAddressEntry(),
|
||||
) ??
|
||||
[]) as P;
|
||||
case 1:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 2:
|
||||
|
@ -341,142 +361,6 @@ extension ContactEntryQueryWhere
|
|||
|
||||
extension ContactEntryQueryFilter
|
||||
on QueryBuilder<ContactEntry, ContactEntry, QFilterCondition> {
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'addresses',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'addresses',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'addresses',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'addresses',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'addresses',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'addresses',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'addresses',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'addresses',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'addresses',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElementIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'addresses',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesLengthEqualTo(int length) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
@ -1055,7 +939,14 @@ extension ContactEntryQueryFilter
|
|||
}
|
||||
|
||||
extension ContactEntryQueryObject
|
||||
on QueryBuilder<ContactEntry, ContactEntry, QFilterCondition> {}
|
||||
on QueryBuilder<ContactEntry, ContactEntry, QFilterCondition> {
|
||||
QueryBuilder<ContactEntry, ContactEntry, QAfterFilterCondition>
|
||||
addressesElement(FilterQuery<ContactAddressEntry> q) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.object(q, r'addresses');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactEntryQueryLinks
|
||||
on QueryBuilder<ContactEntry, ContactEntry, QFilterCondition> {}
|
||||
|
@ -1178,12 +1069,6 @@ extension ContactEntryQuerySortThenBy
|
|||
|
||||
extension ContactEntryQueryWhereDistinct
|
||||
on QueryBuilder<ContactEntry, ContactEntry, QDistinct> {
|
||||
QueryBuilder<ContactEntry, ContactEntry, QDistinct> distinctByAddresses() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'addresses');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, ContactEntry, QDistinct> distinctByCustomId(
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
|
@ -1220,7 +1105,7 @@ extension ContactEntryQueryProperty
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactEntry, List<String>, QQueryOperations>
|
||||
QueryBuilder<ContactEntry, List<ContactAddressEntry>, QQueryOperations>
|
||||
addressesProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'addresses');
|
||||
|
@ -1251,3 +1136,673 @@ extension ContactEntryQueryProperty
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
// IsarEmbeddedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
|
||||
|
||||
const ContactAddressEntrySchema = Schema(
|
||||
name: r'ContactAddressEntry',
|
||||
id: 2556413586404997281,
|
||||
properties: {
|
||||
r'address': PropertySchema(
|
||||
id: 0,
|
||||
name: r'address',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'coinName': PropertySchema(
|
||||
id: 1,
|
||||
name: r'coinName',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'label': PropertySchema(
|
||||
id: 2,
|
||||
name: r'label',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'other': PropertySchema(
|
||||
id: 3,
|
||||
name: r'other',
|
||||
type: IsarType.string,
|
||||
)
|
||||
},
|
||||
estimateSize: _contactAddressEntryEstimateSize,
|
||||
serialize: _contactAddressEntrySerialize,
|
||||
deserialize: _contactAddressEntryDeserialize,
|
||||
deserializeProp: _contactAddressEntryDeserializeProp,
|
||||
);
|
||||
|
||||
int _contactAddressEntryEstimateSize(
|
||||
ContactAddressEntry object,
|
||||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
var bytesCount = offsets.last;
|
||||
bytesCount += 3 + object.address.length * 3;
|
||||
bytesCount += 3 + object.coinName.length * 3;
|
||||
bytesCount += 3 + object.label.length * 3;
|
||||
{
|
||||
final value = object.other;
|
||||
if (value != null) {
|
||||
bytesCount += 3 + value.length * 3;
|
||||
}
|
||||
}
|
||||
return bytesCount;
|
||||
}
|
||||
|
||||
void _contactAddressEntrySerialize(
|
||||
ContactAddressEntry object,
|
||||
IsarWriter writer,
|
||||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
writer.writeString(offsets[0], object.address);
|
||||
writer.writeString(offsets[1], object.coinName);
|
||||
writer.writeString(offsets[2], object.label);
|
||||
writer.writeString(offsets[3], object.other);
|
||||
}
|
||||
|
||||
ContactAddressEntry _contactAddressEntryDeserialize(
|
||||
Id id,
|
||||
IsarReader reader,
|
||||
List<int> offsets,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
final object = ContactAddressEntry();
|
||||
object.address = reader.readString(offsets[0]);
|
||||
object.coinName = reader.readString(offsets[1]);
|
||||
object.label = reader.readString(offsets[2]);
|
||||
object.other = reader.readStringOrNull(offsets[3]);
|
||||
return object;
|
||||
}
|
||||
|
||||
P _contactAddressEntryDeserializeProp<P>(
|
||||
IsarReader reader,
|
||||
int propertyId,
|
||||
int offset,
|
||||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
switch (propertyId) {
|
||||
case 0:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 1:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 2:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 3:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactAddressEntryQueryFilter on QueryBuilder<ContactAddressEntry,
|
||||
ContactAddressEntry, QFilterCondition> {
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'address',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'address',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'address',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'address',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'address',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'address',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'address',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'address',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'address',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
addressIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'address',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'coinName',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'coinName',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'coinName',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'coinName',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'coinName',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'coinName',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'coinName',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'coinName',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'coinName',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
coinNameIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'coinName',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelEqualTo(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'label',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelGreaterThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'label',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelLessThan(
|
||||
String value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'label',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelBetween(
|
||||
String lower,
|
||||
String upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'label',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'label',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'label',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'label',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'label',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'label',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
labelIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'label',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'other',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'other',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherEqualTo(
|
||||
String? value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'other',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherGreaterThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'other',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherLessThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'other',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherBetween(
|
||||
String? lower,
|
||||
String? upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'other',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'other',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'other',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'other',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'other',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'other',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<ContactAddressEntry, ContactAddressEntry, QAfterFilterCondition>
|
||||
otherIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'other',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension ContactAddressEntryQueryObject on QueryBuilder<ContactAddressEntry,
|
||||
ContactAddressEntry, QFilterCondition> {}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,14 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/isar/stack_theme.dart';
|
||||
import 'package:stackwallet/models/notification_model.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/format.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
|
@ -9,7 +16,7 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
|
|||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class NotificationCard extends StatelessWidget {
|
||||
class NotificationCard extends ConsumerWidget {
|
||||
const NotificationCard({
|
||||
Key? key,
|
||||
required this.notification,
|
||||
|
@ -25,8 +32,17 @@ class NotificationCard extends StatelessWidget {
|
|||
static const double mobileIconSize = 24;
|
||||
static const double desktopIconSize = 30;
|
||||
|
||||
String coinIconPath(IThemeAssets assets, WidgetRef ref) {
|
||||
try {
|
||||
final coin = coinFromPrettyName(notification.coinName);
|
||||
return ref.read(coinIconProvider(coin));
|
||||
} catch (_) {
|
||||
return notification.iconAssetName;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
return Stack(
|
||||
|
@ -41,8 +57,14 @@ class NotificationCard extends StatelessWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
notification.changeNowId == null
|
||||
? SvgPicture.asset(
|
||||
notification.iconAssetName,
|
||||
? SvgPicture.file(
|
||||
File(
|
||||
coinIconPath(
|
||||
ref.watch(
|
||||
themeAssetsProvider,
|
||||
),
|
||||
ref),
|
||||
),
|
||||
width: isDesktop ? desktopIconSize : mobileIconSize,
|
||||
height: isDesktop ? desktopIconSize : mobileIconSize,
|
||||
)
|
||||
|
@ -53,8 +75,14 @@ class NotificationCard extends StatelessWidget {
|
|||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
notification.iconAssetName,
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
coinIconPath(
|
||||
ref.watch(
|
||||
themeAssetsProvider,
|
||||
),
|
||||
ref),
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark,
|
||||
|
|
|
@ -120,6 +120,8 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
|
|||
if (Platform.isWindows) {
|
||||
_coins.remove(Coin.monero);
|
||||
_coins.remove(Coin.wownero);
|
||||
} else if (Platform.isLinux) {
|
||||
_coins.remove(Coin.wownero);
|
||||
}
|
||||
|
||||
coinEntities.addAll(_coins.map((e) => CoinEntity(e)));
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
|
@ -73,19 +72,18 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
|
|||
final managers = ref.read(walletsChangeNotifierProvider).managers;
|
||||
for (final manager in managers) {
|
||||
addresses.add(
|
||||
ContactAddressEntry(
|
||||
coin: manager.coin,
|
||||
address: await manager.currentReceivingAddress,
|
||||
label: "Current Receiving",
|
||||
other: manager.walletName,
|
||||
),
|
||||
ContactAddressEntry()
|
||||
..coinName = manager.coin.name
|
||||
..address = await manager.currentReceivingAddress
|
||||
..label = "Current Receiving"
|
||||
..other = manager.walletName,
|
||||
);
|
||||
}
|
||||
final self = Contact(
|
||||
final self = ContactEntry(
|
||||
name: "My Stack",
|
||||
addresses: addresses,
|
||||
isFavorite: true,
|
||||
id: "default",
|
||||
customId: "default",
|
||||
);
|
||||
await ref.read(addressBookServiceProvider).editContact(self);
|
||||
});
|
||||
|
@ -102,7 +100,8 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
final contacts = ref.watch(addressBookServiceProvider.select((value) => value.contacts));
|
||||
final contacts =
|
||||
ref.watch(addressBookServiceProvider.select((value) => value.contacts));
|
||||
|
||||
final isDesktop = Util.isDesktop;
|
||||
return ConditionalParent(
|
||||
|
@ -305,8 +304,8 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
|
|||
.where((element) => element.isFavorite)
|
||||
.map(
|
||||
(e) => AddressBookCard(
|
||||
key: Key("favContactCard_${e.id}_key"),
|
||||
contactId: e.id,
|
||||
key: Key("favContactCard_${e.customId}_key"),
|
||||
contactId: e.customId,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -351,8 +350,9 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
|
|||
.matches(widget.filterTerm ?? _searchTerm, e))
|
||||
.map(
|
||||
(e) => AddressBookCard(
|
||||
key: Key("desktopContactCard_${e.id}_key"),
|
||||
contactId: e.id,
|
||||
key:
|
||||
Key("desktopContactCard_${e.customId}_key"),
|
||||
contactId: e.customId,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -2,8 +2,7 @@ import 'package:emojis/emoji.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
|
@ -28,6 +27,7 @@ import 'package:stackwallet/widgets/emoji_select_sheet.dart';
|
|||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||
import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class AddAddressBookEntryView extends ConsumerStatefulWidget {
|
||||
const AddAddressBookEntryView({
|
||||
|
@ -688,11 +688,12 @@ class _AddAddressBookEntryViewState
|
|||
forms[i].id))
|
||||
.buildAddressEntry());
|
||||
}
|
||||
Contact contact = Contact(
|
||||
ContactEntry contact = ContactEntry(
|
||||
emojiChar: _selectedEmoji?.char,
|
||||
name: nameController.text,
|
||||
addresses: entries,
|
||||
isFavorite: _isFavorite,
|
||||
customId: const Uuid().v1(),
|
||||
);
|
||||
|
||||
if (await ref
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
|
@ -208,7 +207,7 @@ class _AddNewContactAddressViewState
|
|||
.read(addressEntryDataProvider(0))
|
||||
.buildAddressEntry());
|
||||
|
||||
Contact editedContact =
|
||||
ContactEntry editedContact =
|
||||
contact.copyWith(addresses: entries);
|
||||
|
||||
if (await ref
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_image_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
@ -87,8 +89,10 @@ class CoinSelectSheet extends StatelessWidget {
|
|||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinImageProvider(coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinImageProvider(coin)),
|
||||
),
|
||||
height: 20,
|
||||
width: 20,
|
||||
),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
@ -13,8 +15,8 @@ import 'package:stackwallet/providers/global/address_book_service_provider.dart'
|
|||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -197,7 +199,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
onPressed: () {
|
||||
ref
|
||||
.read(addressBookServiceProvider)
|
||||
.removeContact(_contact.id);
|
||||
.removeContact(_contact.customId);
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
showFloatingFlushBar(
|
||||
|
@ -268,7 +270,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
EditContactNameEmojiView.routeName,
|
||||
arguments: _contact.id,
|
||||
arguments: _contact.customId,
|
||||
);
|
||||
},
|
||||
style: Theme.of(context)
|
||||
|
@ -316,7 +318,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
AddNewContactAddressView.routeName,
|
||||
arguments: _contact.id,
|
||||
arguments: _contact.customId,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -334,8 +336,10 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(e.coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(e.coin)),
|
||||
),
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(
|
||||
|
@ -381,7 +385,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
|
||||
Navigator.of(context).pushNamed(
|
||||
EditContactAddressView.routeName,
|
||||
arguments: Tuple2(_contact.id, e),
|
||||
arguments: Tuple2(_contact.customId, e),
|
||||
);
|
||||
},
|
||||
child: RoundedContainer(
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
@ -9,8 +11,8 @@ import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.
|
|||
import 'package:stackwallet/pages/send_view/send_view.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
|
@ -108,13 +110,15 @@ class ContactPopUp extends ConsumerWidget {
|
|||
.textFieldDefaultBG,
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
child: contact.id == "default"
|
||||
child: contact.customId == "default"
|
||||
? Center(
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) =>
|
||||
value.assets.stackIcon,
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value
|
||||
.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 20,
|
||||
|
@ -142,13 +146,13 @@ class ContactPopUp extends ConsumerWidget {
|
|||
STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
),
|
||||
if (contact.id != "default")
|
||||
if (contact.customId != "default")
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.of(context).pushNamed(
|
||||
ContactDetailsView.routeName,
|
||||
arguments: contact.id,
|
||||
arguments: contact.customId,
|
||||
);
|
||||
},
|
||||
style: Theme.of(context)
|
||||
|
@ -172,7 +176,7 @@ class ContactPopUp extends ConsumerWidget {
|
|||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: contact.id == "default" ? 16 : 8,
|
||||
height: contact.customId == "default" ? 16 : 8,
|
||||
),
|
||||
Container(
|
||||
height: 1,
|
||||
|
@ -211,9 +215,11 @@ class ContactPopUp extends ConsumerWidget {
|
|||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
ref.watch(
|
||||
coinIconProvider(e.coin),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(e.coin),
|
||||
),
|
||||
),
|
||||
height: 24,
|
||||
),
|
||||
|
@ -227,14 +233,14 @@ class ContactPopUp extends ConsumerWidget {
|
|||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (contact.id == "default")
|
||||
if (contact.customId == "default")
|
||||
Text(
|
||||
e.other!,
|
||||
style:
|
||||
STextStyles.itemSubtitle12(
|
||||
context),
|
||||
),
|
||||
if (contact.id != "default")
|
||||
if (contact.customId != "default")
|
||||
Text(
|
||||
"${e.label} (${e.coin.ticker})",
|
||||
style:
|
||||
|
@ -330,13 +336,13 @@ class ContactPopUp extends ConsumerWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (contact.id != "default" &&
|
||||
if (contact.customId != "default" &&
|
||||
hasActiveWallet &&
|
||||
!isExchangeFlow)
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
if (contact.id != "default" &&
|
||||
if (contact.customId != "default" &&
|
||||
hasActiveWallet &&
|
||||
!isExchangeFlow)
|
||||
Column(
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/new_contact_address_entry_form.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
|
@ -49,7 +48,7 @@ class _EditContactAddressViewState
|
|||
late final BarcodeScannerInterface barcodeScanner;
|
||||
late final ClipboardInterface clipboard;
|
||||
|
||||
Future<void> save(Contact contact) async {
|
||||
Future<void> save(ContactEntry contact) async {
|
||||
if (FocusScope.of(context).hasFocus) {
|
||||
FocusScope.of(context).unfocus();
|
||||
await Future<void>.delayed(
|
||||
|
@ -73,7 +72,7 @@ class _EditContactAddressViewState
|
|||
|
||||
entries.insert(index, editedEntry);
|
||||
|
||||
Contact editedContact = contact.copyWith(addresses: entries);
|
||||
ContactEntry editedContact = contact.copyWith(addresses: entries);
|
||||
|
||||
if (await ref.read(addressBookServiceProvider).editContact(editedContact)) {
|
||||
if (mounted) {
|
||||
|
@ -226,7 +225,8 @@ class _EditContactAddressViewState
|
|||
);
|
||||
|
||||
_addresses.remove(entry);
|
||||
Contact editedContact = contact.copyWith(addresses: _addresses);
|
||||
ContactEntry editedContact =
|
||||
contact.copyWith(addresses: _addresses);
|
||||
if (await ref
|
||||
.read(addressBookServiceProvider)
|
||||
.editContact(editedContact)) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -7,8 +9,8 @@ import 'package:stackwallet/pages/address_book_views/subviews/coin_select_sheet.
|
|||
import 'package:stackwallet/providers/providers.dart';
|
||||
// import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||
|
@ -141,8 +143,10 @@ class _NewContactAddressEntryFormState
|
|||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
|
@ -211,15 +215,17 @@ class _NewContactAddressEntryFormState
|
|||
)
|
||||
: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(
|
||||
coinIconProvider(
|
||||
ref.watch(
|
||||
addressEntryDataProvider(widget.id)
|
||||
.select(
|
||||
(value) => value.coin,
|
||||
),
|
||||
)!,
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(
|
||||
ref.watch(
|
||||
addressEntryDataProvider(widget.id)
|
||||
.select(
|
||||
(value) => value.coin,
|
||||
),
|
||||
)!,
|
||||
),
|
||||
),
|
||||
),
|
||||
height: 20,
|
||||
|
|
|
@ -113,7 +113,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
String _fetchIconAssetForStatus(String statusString, ThemeAssets assets) {
|
||||
String _fetchIconAssetForStatus(String statusString, IThemeAssets assets) {
|
||||
ChangeNowTransactionStatus? status;
|
||||
try {
|
||||
if (statusString.toLowerCase().startsWith("waiting")) {
|
||||
|
@ -322,11 +322,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
File(
|
||||
_fetchIconAssetForStatus(
|
||||
trade.status,
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets,
|
||||
),
|
||||
),
|
||||
ref.watch(themeAssetsProvider),
|
||||
),
|
||||
),
|
||||
width: 32,
|
||||
|
@ -393,11 +389,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
File(
|
||||
_fetchIconAssetForStatus(
|
||||
trade.status,
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets,
|
||||
),
|
||||
),
|
||||
ref.watch(themeAssetsProvider),
|
||||
),
|
||||
),
|
||||
width: 32,
|
||||
|
@ -1232,7 +1224,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
if (trade.exchangeName
|
||||
.startsWith(TrocadorExchange.exchangeName)) {
|
||||
url =
|
||||
"https://trocador.app/en/checkout${trade.tradeId}";
|
||||
"https://trocador.app/en/checkout/${trade.tradeId}";
|
||||
}
|
||||
}
|
||||
return ConditionalParent(
|
||||
|
|
|
@ -138,10 +138,8 @@ class _PaynymClaimViewState extends ConsumerState<PaynymClaimView> {
|
|||
const Spacer(
|
||||
flex: 1,
|
||||
),
|
||||
Image(
|
||||
image: AssetImage(
|
||||
Assets.svg.unclaimedPaynym,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.unclaimedPaynym,
|
||||
width: MediaQuery.of(context).size.width / 2,
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
|
@ -144,7 +144,7 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
aspectRatio: 1,
|
||||
child: AppBarIconButton(
|
||||
semanticsLabel:
|
||||
"Address List Pop-up Button. Opens A Pop-up For Adress List Button.",
|
||||
"Address List Pop-up Button. Opens A Pop-up For Address List Button.",
|
||||
key: const Key("walletNetworkSettingsAddNewNodeViewButton"),
|
||||
size: 36,
|
||||
shadows: const [],
|
||||
|
|
|
@ -35,6 +35,12 @@ class _ManageExplorerViewState extends ConsumerState<ManageExplorerView> {
|
|||
.replaceAll("%5BTXID%5D", "[TXID]"));
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Background(
|
||||
|
@ -93,13 +99,19 @@ class _ManageExplorerViewState extends ConsumerState<ManageExplorerView> {
|
|||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () {
|
||||
onPressed: () async {
|
||||
textEditingController.text =
|
||||
textEditingController.text.trim();
|
||||
setBlockExplorerForCoin(
|
||||
coin: widget.coin,
|
||||
url: Uri.parse(textEditingController.text))
|
||||
.then((value) => Navigator.of(context).pop());
|
||||
await setBlockExplorerForCoin(
|
||||
coin: widget.coin,
|
||||
url: Uri.parse(
|
||||
textEditingController.text,
|
||||
),
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"Save",
|
||||
|
|
|
@ -225,14 +225,14 @@ class _IncognitoInstalledThemesState
|
|||
extends ConsumerState<IncognitoInstalledThemes> {
|
||||
late final StreamSubscription<void> _subscription;
|
||||
|
||||
List<Tuple2<String, String>> installedThemeIdNames = [];
|
||||
List<Tuple3<String, String, int?>> installedThemeIdNames = [];
|
||||
|
||||
void _updateInstalledList() {
|
||||
installedThemeIdNames = ref
|
||||
.read(pThemeService)
|
||||
.installedThemes
|
||||
.where((e) => e.themeId != "light" && e.themeId != "dark")
|
||||
.map((e) => Tuple2(e.themeId, e.name))
|
||||
.map((e) => Tuple3(e.themeId, e.name, e.version))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
@ -274,6 +274,7 @@ class _IncognitoInstalledThemesState
|
|||
data: StackThemeMetaData(
|
||||
name: e.item2,
|
||||
id: e.item1,
|
||||
version: e.item3 ?? 1,
|
||||
sha256: "",
|
||||
size: "",
|
||||
previewImageUrl: "",
|
||||
|
|
|
@ -39,6 +39,7 @@ class _StackThemeCardState extends ConsumerState<StackThemeCard> {
|
|||
late final StreamSubscription<void> _subscription;
|
||||
|
||||
late bool _hasTheme;
|
||||
bool _needsUpdate = false;
|
||||
String? _cachedSize;
|
||||
|
||||
Future<bool> _downloadAndInstall() async {
|
||||
|
@ -84,6 +85,7 @@ class _StackThemeCardState extends ConsumerState<StackThemeCard> {
|
|||
title: message,
|
||||
onOkPressed: (_) {
|
||||
setState(() {
|
||||
_needsUpdate = !result;
|
||||
_hasTheme = result;
|
||||
});
|
||||
},
|
||||
|
@ -141,16 +143,21 @@ class _StackThemeCardState extends ConsumerState<StackThemeCard> {
|
|||
}
|
||||
}
|
||||
|
||||
StackTheme? getInstalled() => ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.stackThemes
|
||||
.where()
|
||||
.themeIdEqualTo(widget.data.id)
|
||||
.findFirstSync();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_hasTheme = ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.stackThemes
|
||||
.where()
|
||||
.themeIdEqualTo(widget.data.id)
|
||||
.countSync() >
|
||||
0;
|
||||
final installedTheme = getInstalled();
|
||||
_hasTheme = installedTheme != null;
|
||||
if (_hasTheme) {
|
||||
_needsUpdate = widget.data.version > (installedTheme?.version ?? 0);
|
||||
}
|
||||
|
||||
_subscription = ref
|
||||
.read(mainDBProvider)
|
||||
|
@ -158,18 +165,16 @@ class _StackThemeCardState extends ConsumerState<StackThemeCard> {
|
|||
.stackThemes
|
||||
.watchLazy()
|
||||
.listen((event) async {
|
||||
final hasTheme = (await ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.stackThemes
|
||||
.where()
|
||||
.themeIdEqualTo(widget.data.id)
|
||||
.count()) >
|
||||
0;
|
||||
final installedTheme = getInstalled();
|
||||
final hasTheme = installedTheme != null;
|
||||
if (_hasTheme != hasTheme && mounted) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
setState(() {
|
||||
_hasTheme = hasTheme;
|
||||
if (hasTheme) {
|
||||
_needsUpdate =
|
||||
widget.data.version > (installedTheme.version ?? 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -272,6 +277,16 @@ class _StackThemeCardState extends ConsumerState<StackThemeCard> {
|
|||
}
|
||||
},
|
||||
),
|
||||
if (_hasTheme && _needsUpdate)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (_hasTheme && _needsUpdate)
|
||||
PrimaryButton(
|
||||
label: "Update",
|
||||
buttonHeight: isDesktop ? ButtonHeight.s : ButtonHeight.l,
|
||||
onPressed: _downloadPressed,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
|
|
|
@ -191,7 +191,8 @@ class GlobalSettingsView extends StatelessWidget {
|
|||
title: "Appearance",
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
AppearanceSettingsView.routeName);
|
||||
AppearanceSettingsView.routeName,
|
||||
);
|
||||
},
|
||||
),
|
||||
if (Platform.isIOS)
|
||||
|
|
|
@ -718,6 +718,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
|
|||
case Coin.dogecoinTestNet:
|
||||
case Coin.epicCash:
|
||||
case Coin.nano:
|
||||
case Coin.eCash:
|
||||
return false;
|
||||
|
||||
case Coin.ethereum:
|
||||
|
|
|
@ -5,10 +5,9 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/models/stack_restoring_ui_state.dart';
|
||||
import 'package:stackwallet/models/trade_wallet_lookup.dart';
|
||||
|
@ -266,7 +265,7 @@ abstract class SWB {
|
|||
);
|
||||
|
||||
AddressBookService addressBookService = AddressBookService();
|
||||
var addresses = await addressBookService.addressBookEntries;
|
||||
var addresses = addressBookService.contacts;
|
||||
backupJson['addressBookEntries'] =
|
||||
addresses.map((e) => e.toMap()).toList();
|
||||
|
||||
|
@ -799,7 +798,7 @@ abstract class SWB {
|
|||
|
||||
// contacts
|
||||
final addressBookService = AddressBookService();
|
||||
final allContactIds = addressBookService.contacts.map((e) => e.id);
|
||||
final allContactIds = addressBookService.contacts.map((e) => e.customId);
|
||||
|
||||
if (addressBookEntries == null) {
|
||||
// if no contacts were present before attempted restore then delete any that
|
||||
|
@ -823,21 +822,20 @@ abstract class SWB {
|
|||
List<ContactAddressEntry> addresses = [];
|
||||
for (var address in (contact['addresses'] as List<dynamic>)) {
|
||||
addresses.add(
|
||||
ContactAddressEntry(
|
||||
coin: Coin.values
|
||||
.firstWhere((element) => element.name == address['coin']),
|
||||
address: address['address'] as String,
|
||||
label: address['label'] as String,
|
||||
),
|
||||
ContactAddressEntry()
|
||||
..coinName = address['coin'] as String
|
||||
..address = address['address'] as String
|
||||
..label = address['label'] as String
|
||||
..other = address['other'] as String?,
|
||||
);
|
||||
}
|
||||
await addressBookService.editContact(
|
||||
Contact(
|
||||
ContactEntry(
|
||||
emojiChar: contact['emoji'] as String?,
|
||||
name: contact['name'] as String,
|
||||
addresses: addresses,
|
||||
isFavorite: contact['isFavorite'] as bool,
|
||||
id: contact['id'] as String,
|
||||
customId: contact['id'] as String,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
@ -1026,21 +1024,20 @@ abstract class SWB {
|
|||
List<ContactAddressEntry> addresses = [];
|
||||
for (var address in (contact['addresses'] as List<dynamic>)) {
|
||||
addresses.add(
|
||||
ContactAddressEntry(
|
||||
coin: Coin.values
|
||||
.firstWhere((element) => element.name == address['coin']),
|
||||
address: address['address'] as String,
|
||||
label: address['label'] as String,
|
||||
),
|
||||
ContactAddressEntry()
|
||||
..coinName = address['coin'] as String
|
||||
..address = address['address'] as String
|
||||
..label = address['label'] as String
|
||||
..other = address['other'] as String?,
|
||||
);
|
||||
}
|
||||
await addressBookService.addContact(
|
||||
Contact(
|
||||
ContactEntry(
|
||||
emojiChar: contact['emoji'] as String?,
|
||||
name: contact['name'] as String,
|
||||
addresses: addresses,
|
||||
isFavorite: contact['isFavorite'] as bool,
|
||||
id: contact['id'] as String,
|
||||
customId: contact['id'] as String,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
@ -6,8 +8,8 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back
|
|||
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/sub_widgets/restoring_item_card.dart';
|
||||
import 'package:stackwallet/providers/stack_restore/stack_restoring_ui_state_provider.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
|
||||
|
@ -81,8 +83,10 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
.extension<StackColors>()!
|
||||
.colorForCoin(coin),
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
height: 20,
|
||||
width: 20,
|
||||
),
|
||||
|
@ -222,9 +226,11 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
.extension<StackColors>()!
|
||||
.colorForCoin(coin),
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
coinIconProvider(coin),
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(coin),
|
||||
),
|
||||
),
|
||||
height: 20,
|
||||
width: 20,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
|
@ -236,22 +238,24 @@ class _StartupPreferencesViewState
|
|||
.only(top: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(
|
||||
coinIconProvider(
|
||||
ref
|
||||
.watch(
|
||||
walletsChangeNotifierProvider
|
||||
.select(
|
||||
(value) =>
|
||||
value.getManager(
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select((value) => value.startupWalletId!),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(
|
||||
ref
|
||||
.watch(
|
||||
walletsChangeNotifierProvider
|
||||
.select(
|
||||
(value) =>
|
||||
value.getManager(
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select((value) => value.startupWalletId!),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.coin,
|
||||
)
|
||||
.coin,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
|
@ -102,9 +104,11 @@ class _StartupWalletSelectionViewState
|
|||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
coinIconProvider(manager.coin),
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(manager.coin),
|
||||
),
|
||||
),
|
||||
width: 20,
|
||||
height: 20,
|
||||
|
|
|
@ -190,7 +190,7 @@ class AboutItem extends StatelessWidget {
|
|||
height: iconSize,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavIconIcon,
|
||||
.topNavIconPrimary,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
|
||||
|
@ -116,9 +118,11 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
coinIconProvider(manager.coin),
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(manager.coin),
|
||||
),
|
||||
),
|
||||
width: 20,
|
||||
height: 20,
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:qr_flutter/qr_flutter.dart';
|
|||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/services/mixins/xpubable.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
|
@ -177,7 +176,7 @@ class _XPubViewState extends ConsumerState<XPubView> {
|
|||
child: child,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: (manager.wallet as XPubAble).xpub,
|
||||
future: manager.xpub,
|
||||
builder: (context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
|
|
|
@ -33,7 +33,7 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
|
|||
import 'package:tuple/tuple.dart';
|
||||
|
||||
/// [eventBus] should only be set during testing
|
||||
class WalletSettingsView extends StatefulWidget {
|
||||
class WalletSettingsView extends ConsumerStatefulWidget {
|
||||
const WalletSettingsView({
|
||||
Key? key,
|
||||
required this.walletId,
|
||||
|
@ -52,10 +52,10 @@ class WalletSettingsView extends StatefulWidget {
|
|||
final EventBus? eventBus;
|
||||
|
||||
@override
|
||||
State<WalletSettingsView> createState() => _WalletSettingsViewState();
|
||||
ConsumerState<WalletSettingsView> createState() => _WalletSettingsViewState();
|
||||
}
|
||||
|
||||
class _WalletSettingsViewState extends State<WalletSettingsView> {
|
||||
class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
||||
late final String walletId;
|
||||
late final Coin coin;
|
||||
late String xpub;
|
||||
|
@ -74,7 +74,7 @@ class _WalletSettingsViewState extends State<WalletSettingsView> {
|
|||
walletId = widget.walletId;
|
||||
coin = widget.coin;
|
||||
xPubEnabled =
|
||||
coin != Coin.monero && coin != Coin.wownero && coin != Coin.epicCash;
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId).hasXPub;
|
||||
xpub = "";
|
||||
|
||||
_currentSyncStatus = widget.initialSyncStatus;
|
||||
|
|
|
@ -308,14 +308,23 @@ class TokenOptionsButton extends StatelessWidget {
|
|||
child: child,
|
||||
),
|
||||
),
|
||||
child: SvgPicture.file(
|
||||
File(iconAssetPathSVG),
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.tokenSummaryIcon,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
),
|
||||
child: iconAssetPathSVG.startsWith("assets/")
|
||||
? SvgPicture.asset(
|
||||
iconAssetPathSVG,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.tokenSummaryIcon,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
)
|
||||
: SvgPicture.file(
|
||||
File(iconAssetPathSVG),
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.tokenSummaryIcon,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -23,21 +23,8 @@ class TxIcon extends ConsumerWidget {
|
|||
|
||||
static const Size size = Size(32, 32);
|
||||
|
||||
// String _getBundleAssetName(
|
||||
// bool isCancelled, bool isReceived, bool isPending, BuildContext context) {
|
||||
// if (!isReceived && transaction.subType == TransactionSubType.mint) {
|
||||
// if (isCancelled) {
|
||||
// return Assets.svg.anonymizeFailed;
|
||||
// }
|
||||
// if (isPending) {
|
||||
// return Assets.svg.anonymizePending;
|
||||
// }
|
||||
// return Assets.svg.anonymize;
|
||||
// }
|
||||
// }
|
||||
|
||||
String _getAssetName(
|
||||
bool isCancelled, bool isReceived, bool isPending, ThemeAssets assets) {
|
||||
bool isCancelled, bool isReceived, bool isPending, IThemeAssets assets) {
|
||||
if (!isReceived && transaction.subType == TransactionSubType.mint) {
|
||||
if (isCancelled) {
|
||||
return Assets.svg.anonymizeFailed;
|
||||
|
@ -78,7 +65,7 @@ class TxIcon extends ConsumerWidget {
|
|||
currentHeight,
|
||||
coin.requiredConfirmations,
|
||||
),
|
||||
ref.watch(themeProvider).assets,
|
||||
ref.watch(themeAssetsProvider),
|
||||
);
|
||||
|
||||
return SizedBox(
|
||||
|
|
|
@ -3,8 +3,8 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/models/transaction_filter.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
|
||||
|
@ -120,8 +120,8 @@ class _TransactionDetailsViewState extends ConsumerState<AllTransactionsView> {
|
|||
}).toList();
|
||||
}
|
||||
|
||||
bool _isKeywordMatch(Transaction tx, String keyword, List<Contact> contacts,
|
||||
Map<String, String> notes) {
|
||||
bool _isKeywordMatch(Transaction tx, String keyword,
|
||||
List<ContactEntry> contacts, Map<String, String> notes) {
|
||||
if (keyword.isEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/receive_view/addresses/address_details_view.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/tx_icon.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/dialogs/cancelling_transaction_progress_dialog.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/edit_note_view.dart';
|
||||
|
@ -605,17 +607,66 @@ class _TransactionDetailsViewState
|
|||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
_transaction.type ==
|
||||
TransactionType.outgoing
|
||||
? "Sent to"
|
||||
: "Receiving address",
|
||||
style: isDesktop
|
||||
? STextStyles
|
||||
.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
: STextStyles.itemSubtitle(
|
||||
context),
|
||||
ConditionalParent(
|
||||
condition: kDebugMode,
|
||||
builder: (child) {
|
||||
return Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
child,
|
||||
CustomTextButton(
|
||||
text: "Info",
|
||||
onTap: () {
|
||||
if (isDesktop) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) =>
|
||||
DesktopDialog(
|
||||
maxHeight:
|
||||
double.infinity,
|
||||
child:
|
||||
AddressDetailsView(
|
||||
addressId:
|
||||
_transaction
|
||||
.address
|
||||
.value!
|
||||
.id,
|
||||
walletId: widget
|
||||
.walletId,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
Navigator.of(context)
|
||||
.pushNamed(
|
||||
AddressDetailsView
|
||||
.routeName,
|
||||
arguments: Tuple2(
|
||||
_transaction.address
|
||||
.value!.id,
|
||||
widget.walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
_transaction.type ==
|
||||
TransactionType.outgoing
|
||||
? "Sent to"
|
||||
: "Receiving address",
|
||||
style: isDesktop
|
||||
? STextStyles
|
||||
.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
: STextStyles.itemSubtitle(
|
||||
context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
|
@ -1099,6 +1150,46 @@ class _TransactionDetailsViewState
|
|||
],
|
||||
),
|
||||
),
|
||||
if (kDebugMode)
|
||||
isDesktop
|
||||
? const _Divider()
|
||||
: const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (kDebugMode)
|
||||
RoundedWhiteContainer(
|
||||
padding: isDesktop
|
||||
? const EdgeInsets.all(16)
|
||||
: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Tx sub type",
|
||||
style: isDesktop
|
||||
? STextStyles
|
||||
.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
SelectableText(
|
||||
_transaction.subType.toString(),
|
||||
style: isDesktop
|
||||
? STextStyles
|
||||
.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
)
|
||||
: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
isDesktop
|
||||
? const _Divider()
|
||||
: const SizedBox(
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/add_address_book_entry_view.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/address_book_filter_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_book_scaffold.dart';
|
||||
|
@ -105,19 +104,18 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
|
|||
final managers = ref.read(walletsChangeNotifierProvider).managers;
|
||||
for (final manager in managers) {
|
||||
addresses.add(
|
||||
ContactAddressEntry(
|
||||
coin: manager.coin,
|
||||
address: await manager.currentReceivingAddress,
|
||||
label: "Current Receiving",
|
||||
other: manager.walletName,
|
||||
),
|
||||
ContactAddressEntry()
|
||||
..coinName = manager.coin.name
|
||||
..address = await manager.currentReceivingAddress
|
||||
..label = "Current Receiving"
|
||||
..other = manager.walletName,
|
||||
);
|
||||
}
|
||||
final self = Contact(
|
||||
final self = ContactEntry(
|
||||
name: "My Stack",
|
||||
addresses: addresses,
|
||||
isFavorite: true,
|
||||
id: "default",
|
||||
customId: "default",
|
||||
);
|
||||
await ref.read(addressBookServiceProvider).editContact(self);
|
||||
});
|
||||
|
@ -323,14 +321,14 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
|
|||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(
|
||||
currentContactId == favorites[i].id
|
||||
currentContactId == favorites[i].customId
|
||||
? 0.08
|
||||
: 0,
|
||||
),
|
||||
child: RawMaterialButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
currentContactId = favorites[i].id;
|
||||
currentContactId = favorites[i].customId;
|
||||
});
|
||||
},
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
@ -346,8 +344,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
|
|||
),
|
||||
child: AddressBookCard(
|
||||
key: Key(
|
||||
"favContactCard_${favorites[i].id}_key"),
|
||||
contactId: favorites[i].id,
|
||||
"favContactCard_${favorites[i].customId}_key"),
|
||||
contactId: favorites[i].customId,
|
||||
desktopSendFrom: false,
|
||||
),
|
||||
),
|
||||
|
@ -393,14 +391,16 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
|
|||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(
|
||||
currentContactId == allContacts[i].id
|
||||
currentContactId ==
|
||||
allContacts[i].customId
|
||||
? 0.08
|
||||
: 0,
|
||||
),
|
||||
child: RawMaterialButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
currentContactId = allContacts[i].id;
|
||||
currentContactId =
|
||||
allContacts[i].customId;
|
||||
});
|
||||
},
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
@ -416,8 +416,8 @@ class _DesktopAddressBook extends ConsumerState<DesktopAddressBook> {
|
|||
),
|
||||
child: AddressBookCard(
|
||||
key: Key(
|
||||
"favContactCard_${allContacts[i].id}_key"),
|
||||
contactId: allContacts[i].id,
|
||||
"favContactCard_${allContacts[i].customId}_key"),
|
||||
contactId: allContacts[i].customId,
|
||||
desktopSendFrom: false,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/address_book_view/subwidgets/desktop_address_card.dart';
|
||||
|
@ -24,8 +27,6 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
|
|||
import 'package:stackwallet/widgets/transaction_card.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../../../db/isar/main_db.dart';
|
||||
|
||||
class DesktopContactDetails extends ConsumerStatefulWidget {
|
||||
const DesktopContactDetails({
|
||||
Key? key,
|
||||
|
@ -42,7 +43,7 @@ class DesktopContactDetails extends ConsumerStatefulWidget {
|
|||
class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
|
||||
List<Tuple2<String, Transaction>> _cachedTransactions = [];
|
||||
|
||||
bool _contactHasAddress(String address, Contact contact) {
|
||||
bool _contactHasAddress(String address, ContactEntry contact) {
|
||||
for (final entry in contact.addresses) {
|
||||
if (entry.address == address) {
|
||||
return true;
|
||||
|
@ -82,7 +83,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// provider hack to prevent trying to update widget with deleted contact
|
||||
Contact? _contact;
|
||||
ContactEntry? _contact;
|
||||
try {
|
||||
_contact = ref.watch(addressBookServiceProvider
|
||||
.select((value) => value.getContactById(widget.contactId)));
|
||||
|
@ -110,19 +111,21 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
|
|||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: contact.id == "default"
|
||||
color: contact.customId == "default"
|
||||
? Colors.transparent
|
||||
: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
child: contact.id == "default"
|
||||
child: contact.customId == "default"
|
||||
? Center(
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 32,
|
||||
|
@ -159,7 +162,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
|
|||
barrierColor: Colors.transparent,
|
||||
builder: (context) {
|
||||
return DesktopContactOptionsMenuPopup(
|
||||
contactId: contact.id,
|
||||
contactId: contact.customId,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -261,7 +264,7 @@ class _DesktopContactDetailsState extends ConsumerState<DesktopContactDetails> {
|
|||
padding: const EdgeInsets.all(18),
|
||||
child: DesktopAddressCard(
|
||||
entry: contact.addresses[i],
|
||||
contactId: contact.id,
|
||||
contactId: contact.customId,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -147,7 +147,7 @@ class _DesktopContactOptionsMenuPopupState
|
|||
onPressed: () {
|
||||
ref
|
||||
.read(addressBookServiceProvider)
|
||||
.removeContact(contact.id);
|
||||
.removeContact(contact.customId);
|
||||
Navigator.of(context).pop();
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.success,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
@ -6,8 +8,8 @@ import 'package:stackwallet/db/isar/main_db.dart';
|
|||
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
|
@ -359,8 +361,10 @@ class _DesktopCoinControlUseDialogState
|
|||
color: Colors.transparent,
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
@ -7,8 +9,8 @@ import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
|
|||
import 'package:stackwallet/pages_desktop_specific/coin_control/freeze_button.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/coin_control/utxo_row.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -343,8 +345,10 @@ class _DesktopCoinControlViewState
|
|||
color: Colors.transparent,
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -287,7 +288,7 @@ class DesktopTradeRowCard extends ConsumerStatefulWidget {
|
|||
class _DesktopTradeRowCardState extends ConsumerState<DesktopTradeRowCard> {
|
||||
late final String tradeId;
|
||||
|
||||
String _fetchIconAssetForStatus(String statusString, ThemeAssets assets) {
|
||||
String _fetchIconAssetForStatus(String statusString, IThemeAssets assets) {
|
||||
ChangeNowTransactionStatus? status;
|
||||
try {
|
||||
if (statusString.toLowerCase().startsWith("waiting")) {
|
||||
|
@ -522,10 +523,14 @@ class _DesktopTradeRowCardState extends ConsumerState<DesktopTradeRowCard> {
|
|||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
_fetchIconAssetForStatus(
|
||||
trade.status,
|
||||
ref.watch(themeProvider.select((value) => value.assets)),
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
_fetchIconAssetForStatus(
|
||||
trade.status,
|
||||
ref.watch(
|
||||
themeAssetsProvider,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 32,
|
||||
height: 32,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
@ -61,8 +63,8 @@ class DesktopBuyIcon extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return SvgPicture.asset(
|
||||
ref.watch(themeProvider.select((value) => value.assets.buy)),
|
||||
return SvgPicture.file(
|
||||
File(ref.watch(themeAssetsProvider).buy),
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: DesktopMenuItemId.buy ==
|
||||
|
@ -81,28 +83,36 @@ class DesktopNotificationsIcon extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return SvgPicture.asset(
|
||||
ref.watch(notificationsProvider
|
||||
.select((value) => value.hasUnreadNotifications))
|
||||
? ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.bellNew,
|
||||
return ref.watch(notificationsProvider
|
||||
.select((value) => value.hasUnreadNotifications))
|
||||
? SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.bellNew,
|
||||
),
|
||||
),
|
||||
)
|
||||
: Assets.svg.bell,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: ref.watch(notificationsProvider
|
||||
.select((value) => value.hasUnreadNotifications))
|
||||
? null
|
||||
: DesktopMenuItemId.notifications ==
|
||||
ref.watch(currentDesktopMenuItemProvider.state).state
|
||||
? Theme.of(context).extension<StackColors>()!.accentColorDark
|
||||
: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(0.8),
|
||||
);
|
||||
),
|
||||
width: 20,
|
||||
height: 20,
|
||||
)
|
||||
: SvgPicture.asset(
|
||||
Assets.svg.bell,
|
||||
width: 20,
|
||||
height: 20,
|
||||
color: ref.watch(notificationsProvider
|
||||
.select((value) => value.hasUnreadNotifications))
|
||||
? null
|
||||
: DesktopMenuItemId.notifications ==
|
||||
ref.watch(currentDesktopMenuItemProvider.state).state
|
||||
? Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark
|
||||
.withOpacity(0.8),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
@ -53,10 +55,12 @@ class DesktopMyStackTitle extends ConsumerWidget {
|
|||
SizedBox(
|
||||
width: 32,
|
||||
height: 32,
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
@ -10,8 +12,8 @@ import 'package:stackwallet/providers/global/price_provider.dart';
|
|||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
|
@ -81,8 +83,10 @@ class _DesktopPaynymSendDialogState
|
|||
// Theme.of(context).extension<StackColors>()!.textSubtitle4,
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
width: 36,
|
||||
height: 36,
|
||||
),
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages/wallets_view/wallets_overview.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
|
@ -141,8 +143,10 @@ class _DesktopWalletSummaryRowState
|
|||
flex: 4,
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(widget.coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(widget.coin)),
|
||||
),
|
||||
width: 28,
|
||||
height: 28,
|
||||
),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
|
@ -34,7 +34,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
|
||||
String _searchTerm = "";
|
||||
|
||||
int _compareContactFavorite(Contact a, Contact b) {
|
||||
int _compareContactFavorite(ContactEntry a, ContactEntry b) {
|
||||
if (a.isFavorite && b.isFavorite) {
|
||||
return 0;
|
||||
} else if (a.isFavorite) {
|
||||
|
@ -44,8 +44,8 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
}
|
||||
}
|
||||
|
||||
List<Contact> pullOutFavorites(List<Contact> contacts) {
|
||||
final List<Contact> favorites = [];
|
||||
List<ContactEntry> pullOutFavorites(List<ContactEntry> contacts) {
|
||||
final List<ContactEntry> favorites = [];
|
||||
contacts.removeWhere((contact) {
|
||||
if (contact.isFavorite) {
|
||||
favorites.add(contact);
|
||||
|
@ -57,7 +57,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
return favorites;
|
||||
}
|
||||
|
||||
List<Contact> filter(List<Contact> contacts, String searchTerm) {
|
||||
List<ContactEntry> filter(List<ContactEntry> contacts, String searchTerm) {
|
||||
if (widget.coin != null) {
|
||||
contacts.removeWhere(
|
||||
(e) => e.addresses.where((a) => a.coin == widget.coin!).isEmpty);
|
||||
|
@ -75,7 +75,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
return contacts;
|
||||
}
|
||||
|
||||
bool _matches(String term, Contact contact) {
|
||||
bool _matches(String term, ContactEntry contact) {
|
||||
final text = term.toLowerCase();
|
||||
if (contact.name.toLowerCase().contains(text)) {
|
||||
return true;
|
||||
|
@ -191,7 +191,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
),
|
||||
child: Consumer(
|
||||
builder: (context, ref, _) {
|
||||
List<Contact> contacts = ref
|
||||
List<ContactEntry> contacts = ref
|
||||
.watch(addressBookServiceProvider
|
||||
.select((value) => value.contacts))
|
||||
.toList();
|
||||
|
@ -228,7 +228,7 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
),
|
||||
);
|
||||
} else if (index < favorites.length + 1) {
|
||||
final id = favorites[index - 1].id;
|
||||
final id = favorites[index - 1].customId;
|
||||
return ContactListItem(
|
||||
key: Key("contactContactListItem_${id}_key"),
|
||||
contactId: id,
|
||||
|
@ -248,7 +248,8 @@ class _AddressBookAddressChooserState extends State<AddressBookAddressChooser> {
|
|||
),
|
||||
);
|
||||
} else {
|
||||
final id = contacts[index - favorites.length - 2].id;
|
||||
final id =
|
||||
contacts[index - favorites.length - 2].customId;
|
||||
return ContactListItem(
|
||||
key: Key("contactContactListItem_${id}_key"),
|
||||
contactId: id,
|
||||
|
|
|
@ -69,7 +69,7 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
|
|||
_MoreFeaturesItem(
|
||||
label: "Anonymize funds",
|
||||
detail: "Anonymize funds",
|
||||
iconAsset: Assets.svg.anonymize,
|
||||
iconAsset: Assets.svg.recycle,
|
||||
onPressed: () => widget.onAnonymizeAllPressed?.call(),
|
||||
),
|
||||
if (manager.hasWhirlpoolSupport)
|
||||
|
|
|
@ -94,10 +94,12 @@ class _ForgotPasswordDesktopViewState
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 100,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
@ -54,7 +55,7 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
|
|||
int dbVersion = DB.instance.get<dynamic>(
|
||||
boxName: DB.boxNameDBInfo, key: "hive_data_version") as int? ??
|
||||
0;
|
||||
if (dbVersion < Constants.currentHiveDbVersion) {
|
||||
if (dbVersion < Constants.currentDataVersion) {
|
||||
try {
|
||||
await DbVersionMigrator().migrate(
|
||||
dbVersion,
|
||||
|
@ -166,10 +167,12 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 100,
|
||||
|
@ -249,7 +252,7 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
|
|||
),
|
||||
suffixIcon: UnconstrainedBox(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
height: 40,
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
@ -47,10 +49,12 @@ class _ForgotPasswordDesktopViewState
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 100,
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/debug_info_dialog.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/desktop_manage_block_explorers_dialog.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/settings/settings_menu/advanced_settings/stack_privacy_dialog.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
|
@ -58,7 +59,7 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
|
|||
),
|
||||
TextSpan(
|
||||
text:
|
||||
"\n\nConfigurate these settings only if you know what you are doing!",
|
||||
"\n\nConfigure these settings only if you know what you are doing!",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context),
|
||||
),
|
||||
|
@ -183,7 +184,7 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
|
|||
PrimaryButton(
|
||||
label: "Change",
|
||||
buttonHeight: ButtonHeight.xs,
|
||||
width: 86,
|
||||
width: 101,
|
||||
onPressed: () async {
|
||||
await showDialog<dynamic>(
|
||||
context: context,
|
||||
|
@ -207,8 +208,6 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
|
|||
thickness: 0.5,
|
||||
),
|
||||
),
|
||||
|
||||
/// TODO: Make a dialog popup
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
|
@ -241,6 +240,44 @@ class _AdvancedSettings extends ConsumerState<AdvancedSettings> {
|
|||
],
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: Divider(
|
||||
thickness: 0.5,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Block explorers",
|
||||
style: STextStyles.desktopTextExtraSmall(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
PrimaryButton(
|
||||
buttonHeight: ButtonHeight.xs,
|
||||
label: "Edit",
|
||||
width: 101,
|
||||
onPressed: () async {
|
||||
await showDialog<dynamic>(
|
||||
context: context,
|
||||
useSafeArea: false,
|
||||
barrierDismissible: true,
|
||||
builder: (context) {
|
||||
return const DesktopManageBlockExplorersDialog();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/block_explorers.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class DesktopManageBlockExplorersDialog extends ConsumerWidget {
|
||||
const DesktopManageBlockExplorersDialog({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
bool showTestNet = ref.watch(
|
||||
prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
|
||||
);
|
||||
|
||||
final List<Coin> coins = showTestNet
|
||||
? Coin.values
|
||||
: Coin.values.sublist(0, Coin.values.length - kTestNetCoinCount);
|
||||
|
||||
return DesktopDialog(
|
||||
maxHeight: 850,
|
||||
maxWidth: 600,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Text(
|
||||
"Manage block explorers",
|
||||
style: STextStyles.desktopH3(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
const DesktopDialogCloseButton(),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 32,
|
||||
right: 32,
|
||||
bottom: 32,
|
||||
),
|
||||
child: ListView.separated(
|
||||
itemCount: coins.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
itemBuilder: (_, index) {
|
||||
final coin = coins[index];
|
||||
|
||||
return RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 14,
|
||||
),
|
||||
borderColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textSubtitle6,
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${coin.prettyName} block explorer",
|
||||
style: STextStyles.desktopTextSmall(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
SvgPicture.asset(
|
||||
Assets.svg.chevronRight,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
showDialog<dynamic>(
|
||||
context: context,
|
||||
useSafeArea: false,
|
||||
barrierDismissible: true,
|
||||
builder: (context) {
|
||||
return _DesktopEditBlockExplorerDialog(
|
||||
coin: coin,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DesktopEditBlockExplorerDialog extends ConsumerStatefulWidget {
|
||||
const _DesktopEditBlockExplorerDialog({Key? key, required this.coin})
|
||||
: super(key: key);
|
||||
|
||||
final Coin coin;
|
||||
|
||||
@override
|
||||
ConsumerState<_DesktopEditBlockExplorerDialog> createState() =>
|
||||
_DesktopEditBlockExplorerDialogState();
|
||||
}
|
||||
|
||||
class _DesktopEditBlockExplorerDialogState
|
||||
extends ConsumerState<_DesktopEditBlockExplorerDialog> {
|
||||
late final TextEditingController _textEditingController;
|
||||
late final FocusNode _focusNode;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_textEditingController = TextEditingController(
|
||||
text:
|
||||
getBlockExplorerTransactionUrlFor(coin: widget.coin, txid: "[TXID]")
|
||||
.toString()
|
||||
.replaceAll("%5BTXID%5D", "[TXID]"));
|
||||
_focusNode = FocusNode();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textEditingController.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DesktopDialog(
|
||||
maxHeight: double.infinity,
|
||||
maxWidth: 600,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Text(
|
||||
"${widget.coin.prettyName} block explorer",
|
||||
style: STextStyles.desktopH3(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
const DesktopDialogCloseButton(),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 32,
|
||||
right: 32,
|
||||
bottom: 32,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
child: TextField(
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
key: const Key("addCustomNodeNodeAddressFieldKey"),
|
||||
controller: _textEditingController,
|
||||
focusNode: _focusNode,
|
||||
style: STextStyles.field(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
RoundedWhiteContainer(
|
||||
borderColor:
|
||||
Theme.of(context).extension<StackColors>()!.textSubtitle6,
|
||||
child: Text(
|
||||
"Edit your block explorer above. Keep in mind that"
|
||||
" every block explorer has a slightly different URL scheme."
|
||||
"\n\n"
|
||||
"Paste in your block explorer of choice, then edit in"
|
||||
" [TXID] where the transaction ID should go, and Stack"
|
||||
" Wallet will auto fill the transaction ID in that place"
|
||||
" of the URL.",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SecondaryButton(
|
||||
label: "Cancel",
|
||||
buttonHeight: ButtonHeight.l,
|
||||
onPressed: Navigator.of(context).pop,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
Expanded(
|
||||
child: PrimaryButton(
|
||||
label: "Save",
|
||||
buttonHeight: ButtonHeight.l,
|
||||
onPressed: () async {
|
||||
_textEditingController.text =
|
||||
_textEditingController.text.trim();
|
||||
await setBlockExplorerForCoin(
|
||||
coin: widget.coin,
|
||||
url: Uri.parse(
|
||||
_textEditingController.text,
|
||||
),
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -118,44 +118,6 @@ class _AppearanceOptionSettings
|
|||
],
|
||||
),
|
||||
),
|
||||
// const Padding(
|
||||
// padding: EdgeInsets.all(10.0),
|
||||
// child: Divider(
|
||||
// thickness: 0.5,
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(10.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// "System brightness",
|
||||
// style: STextStyles.desktopTextExtraSmall(context)
|
||||
// .copyWith(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .textDark),
|
||||
// textAlign: TextAlign.left,
|
||||
// ),
|
||||
// SizedBox(
|
||||
// height: 20,
|
||||
// width: 40,
|
||||
// child: DraggableSwitchButton(
|
||||
// isOn: ref.watch(
|
||||
// prefsChangeNotifierProvider.select(
|
||||
// (value) => value.enableSystemBrightness),
|
||||
// ),
|
||||
// onValueChanged: (newValue) {
|
||||
// ref
|
||||
// .read(prefsChangeNotifierProvider)
|
||||
// .enableSystemBrightness = newValue;
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: Divider(
|
||||
|
|
|
@ -6,8 +6,8 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -58,6 +58,8 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
|
|||
if (Platform.isWindows) {
|
||||
_coins.remove(Coin.monero);
|
||||
_coins.remove(Coin.wownero);
|
||||
} else if (Platform.isLinux) {
|
||||
_coins.remove(Coin.wownero);
|
||||
}
|
||||
|
||||
searchNodeController = TextEditingController();
|
||||
|
@ -250,8 +252,10 @@ class _NodesSettings extends ConsumerState<NodesSettings> {
|
|||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
SvgPicture.file(
|
||||
File(
|
||||
ref.watch(coinIconProvider(coin)),
|
||||
),
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:isar/isar.dart';
|
|||
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
|
||||
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
|
||||
import 'package:stackwallet/models/buy/response_objects/quote.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
|
@ -153,6 +152,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|||
import 'package:stackwallet/widgets/choose_coin_view.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import 'models/isar/models/contact_entry.dart';
|
||||
|
||||
class RouteGenerator {
|
||||
static const bool useMaterialPageRoute = true;
|
||||
|
||||
|
|
|
@ -1,107 +1,33 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/contact_address_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
||||
class AddressBookService extends ChangeNotifier {
|
||||
|
||||
ContactEntry turnContactToEntry({required Contact contact}) {
|
||||
String? emojiChar = contact.emojiChar;
|
||||
String name = contact.name;
|
||||
List<String> addresses = [];
|
||||
bool isFavorite = contact.isFavorite;
|
||||
String customId = contact.id;
|
||||
for (ContactAddressEntry contactAddressEntry in contact.addresses) {
|
||||
String coin = contactAddressEntry.coin.ticker;
|
||||
String address = contactAddressEntry.address;
|
||||
String label = contactAddressEntry.label;
|
||||
String? other = contactAddressEntry.other;
|
||||
addresses.add("$coin,$address,$label,$other");
|
||||
}
|
||||
return ContactEntry(
|
||||
emojiChar: emojiChar,
|
||||
name: name,
|
||||
addresses: addresses,
|
||||
isFavorite: isFavorite,
|
||||
customId: customId,
|
||||
);
|
||||
}
|
||||
|
||||
Contact turnEntryToContact({required ContactEntry contactEntry}) {
|
||||
String? emojiChar = contactEntry.emojiChar;
|
||||
String name = contactEntry.name;
|
||||
List<ContactAddressEntry> addresses = [];
|
||||
bool isFavorite = contactEntry.isFavorite;
|
||||
String id = contactEntry.customId;
|
||||
for (String addressEntry in contactEntry.addresses) {
|
||||
List<String> addressEntrySplit = addressEntry.split(",");
|
||||
Coin coin = coinFromTickerCaseInsensitive(addressEntrySplit[0]);
|
||||
String address = addressEntrySplit[1];
|
||||
String label = addressEntrySplit[2];
|
||||
String? other = addressEntrySplit[3];
|
||||
addresses.add(ContactAddressEntry(
|
||||
coin: coin,
|
||||
address: address,
|
||||
label: label,
|
||||
other: other,
|
||||
));
|
||||
}
|
||||
return Contact(
|
||||
emojiChar: emojiChar,
|
||||
name: name,
|
||||
addresses: addresses,
|
||||
isFavorite: isFavorite,
|
||||
id: id,
|
||||
);
|
||||
}
|
||||
|
||||
Contact getContactById(String id) {
|
||||
ContactEntry getContactById(String id) {
|
||||
ContactEntry? contactEntry = MainDB.instance.getContactEntry(id: id);
|
||||
if (contactEntry == null) {
|
||||
return Contact(
|
||||
name: "Contact not found",
|
||||
addresses: [],
|
||||
isFavorite: false,
|
||||
);
|
||||
throw Exception('Contact ID "$id" not found!');
|
||||
} else {
|
||||
return turnEntryToContact(contactEntry: contactEntry);
|
||||
return contactEntry;
|
||||
}
|
||||
}
|
||||
|
||||
List<Contact> get contacts {
|
||||
List<ContactEntry> contactEntries = MainDB.instance.getContactEntries();
|
||||
List<Contact> contactsList = [];
|
||||
for (ContactEntry contactEntry in contactEntries) {
|
||||
contactsList.add(turnEntryToContact(contactEntry: contactEntry));
|
||||
}
|
||||
return contactsList;
|
||||
}
|
||||
|
||||
List<Contact>? _addressBookEntries;
|
||||
List<Contact> get addressBookEntries =>
|
||||
_addressBookEntries ??= _fetchAddressBookEntries();
|
||||
|
||||
// Load address book contact entries
|
||||
List<Contact> _fetchAddressBookEntries() {
|
||||
return contacts;
|
||||
}
|
||||
List<ContactEntry> get contacts => MainDB.instance.getContactEntries();
|
||||
|
||||
/// search address book entries
|
||||
//TODO optimize address book search?
|
||||
Future<List<Contact>> search(String text) async {
|
||||
if (text.isEmpty) return addressBookEntries;
|
||||
var results = (await addressBookEntries).toList();
|
||||
//TODO search using isar queries
|
||||
Future<List<ContactEntry>> search(String text) async {
|
||||
if (text.isEmpty) return contacts;
|
||||
var results = contacts.toList();
|
||||
|
||||
results.retainWhere((contact) => matches(text, contact));
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
bool matches(String term, Contact contact) {
|
||||
bool matches(String term, ContactEntry contact) {
|
||||
if (term.isEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
@ -125,33 +51,27 @@ class AddressBookService extends ChangeNotifier {
|
|||
///
|
||||
/// returns false if it provided [contact]'s id already exists in the database
|
||||
/// other true if the [contact] was saved
|
||||
Future<bool> addContact(Contact contact) async {
|
||||
if (await MainDB.instance.isContactEntryExists(id: contact.id)) {
|
||||
Future<bool> addContact(ContactEntry contact) async {
|
||||
if (await MainDB.instance.isContactEntryExists(id: contact.customId)) {
|
||||
return false;
|
||||
} else {
|
||||
await MainDB.instance.putContactEntry(contactEntry: turnContactToEntry(contact: contact));
|
||||
_refreshAddressBookEntries();
|
||||
await MainDB.instance.putContactEntry(contactEntry: contact);
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Edit contact
|
||||
Future<bool> editContact(Contact editedContact) async {
|
||||
Future<bool> editContact(ContactEntry editedContact) async {
|
||||
// over write the contact with edited version
|
||||
await MainDB.instance.putContactEntry(contactEntry: turnContactToEntry(contact: editedContact));
|
||||
_refreshAddressBookEntries();
|
||||
await MainDB.instance.putContactEntry(contactEntry: editedContact);
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Remove address book contact entry from db if it exists
|
||||
Future<void> removeContact(String id) async {
|
||||
await MainDB.instance.deleteContactEntry(id: id);
|
||||
_refreshAddressBookEntries();
|
||||
}
|
||||
|
||||
void _refreshAddressBookEntries() {
|
||||
final newAddressBookEntries = _fetchAddressBookEntries();
|
||||
_addressBookEntries = newAddressBookEntries;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,11 +53,11 @@ import 'package:uuid/uuid.dart';
|
|||
const int MINIMUM_CONFIRMATIONS = 1;
|
||||
final Amount DUST_LIMIT = Amount(
|
||||
rawValue: BigInt.from(294),
|
||||
fractionDigits: Coin.particl.decimals,
|
||||
fractionDigits: Coin.bitcoin.decimals,
|
||||
);
|
||||
final Amount DUST_LIMIT_P2PKH = Amount(
|
||||
rawValue: BigInt.from(546),
|
||||
fractionDigits: Coin.particl.decimals,
|
||||
fractionDigits: Coin.bitcoin.decimals,
|
||||
);
|
||||
|
||||
const String GENESIS_HASH_MAINNET =
|
||||
|
@ -1468,7 +1468,7 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
value: bip39.generateMnemonic(strength: 128));
|
||||
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
|
|
|
@ -71,7 +71,6 @@ String constructDerivePath({
|
|||
case 0x80: // bch mainnet wif
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
case DerivePathType.bip49:
|
||||
coinType = 145; // bch mainnet
|
||||
break;
|
||||
case DerivePathType.bch44: // bitcoin.com wallet specific
|
||||
|
@ -95,9 +94,6 @@ String constructDerivePath({
|
|||
case DerivePathType.bch44:
|
||||
purpose = 44;
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
purpose = 49;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
|
@ -283,10 +279,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
return DerivePathType.bip44;
|
||||
}
|
||||
|
||||
if (decodeBase58[0] == _network.scriptHash) {
|
||||
// P2SH
|
||||
return DerivePathType.bip49;
|
||||
}
|
||||
throw ArgumentError('Invalid version or Network mismatch');
|
||||
} else {
|
||||
try {
|
||||
|
@ -419,15 +411,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
addrType = isar_models.AddressType.p2pkh;
|
||||
addressString = bitbox.Address.toCashAddress(addressString);
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
addressString = P2SH(
|
||||
data: PaymentData(
|
||||
redeem: P2WPKH(data: data, network: _network).data),
|
||||
network: _network)
|
||||
.data
|
||||
.address!;
|
||||
addrType = isar_models.AddressType.p2sh;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType $type not supported");
|
||||
}
|
||||
|
@ -518,7 +501,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
|
||||
final deriveTypes = [
|
||||
DerivePathType.bip44,
|
||||
DerivePathType.bip49,
|
||||
];
|
||||
|
||||
if (coin != Coin.bitcoincashTestnet) {
|
||||
|
@ -1389,7 +1371,7 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
value: bip39.generateMnemonic(strength: 128));
|
||||
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
|
@ -1397,10 +1379,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
// P2PKH
|
||||
_generateAddressForChain(0, 0, DerivePathType.bip44),
|
||||
_generateAddressForChain(1, 0, DerivePathType.bip44),
|
||||
|
||||
// P2SH
|
||||
_generateAddressForChain(0, 0, DerivePathType.bip49),
|
||||
_generateAddressForChain(1, 0, DerivePathType.bip49),
|
||||
]);
|
||||
|
||||
await db.putAddresses(initialAddresses);
|
||||
|
@ -1408,7 +1386,7 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info);
|
||||
}
|
||||
|
||||
/// Generates a new internal or external chain address for the wallet using a BIP44 or BIP49 derivation path.
|
||||
/// Generates a new internal or external chain address for the wallet using a BIP44 derivation path.
|
||||
/// [chain] - Use 0 for receiving (external), 1 for change (internal). Should not be any other value!
|
||||
/// [index] - This can be any integer >= 0
|
||||
Future<isar_models.Address> _generateAddressForChain(
|
||||
|
@ -1449,17 +1427,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
addrType = isar_models.AddressType.p2pkh;
|
||||
address = bitbox.Address.toCashAddress(address);
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
address = P2SH(
|
||||
data: PaymentData(
|
||||
redeem: P2WPKH(data: data, network: _network).data),
|
||||
network: _network)
|
||||
.data
|
||||
.address!;
|
||||
addrType = isar_models.AddressType.p2sh;
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
throw UnsupportedError("bip84 not supported by BCH");
|
||||
default:
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
|
@ -1502,13 +1469,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
coinType = coin == Coin.bitcoincash ? "0" : "1";
|
||||
purpose = "44";
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
type = isar_models.AddressType.p2sh;
|
||||
coinType = coin == Coin.bitcoincash ? "145" : "1";
|
||||
purpose = "49";
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
throw UnsupportedError("bip84 not supported by BCH");
|
||||
default:
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
|
@ -1537,9 +1497,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
case DerivePathType.bch44:
|
||||
key = "${walletId}_${chainId}DerivationsBch44P2PKH";
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
key = "${walletId}_${chainId}DerivationsP2SH";
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError(
|
||||
"${derivePathType.name} not supported by ${coin.prettyName}");
|
||||
|
@ -2721,20 +2678,6 @@ class BitcoinCashWallet extends CoinServiceAPI
|
|||
redeemScript = null;
|
||||
break;
|
||||
|
||||
case DerivePathType.bip49:
|
||||
final p2wpkh = P2WPKH(
|
||||
data: PaymentData(
|
||||
pubkey: Format.stringToUint8List(pubKey),
|
||||
),
|
||||
network: _network,
|
||||
).data;
|
||||
redeemScript = p2wpkh.output;
|
||||
data = P2SH(
|
||||
data: PaymentData(redeem: p2wpkh),
|
||||
network: _network,
|
||||
).data;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
|||
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/ecash/ecash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
|
@ -243,6 +244,17 @@ abstract class CoinServiceAPI {
|
|||
cachedClient: cachedClient,
|
||||
tracker: tracker,
|
||||
);
|
||||
|
||||
case Coin.eCash:
|
||||
return ECashWallet(
|
||||
walletId: walletId,
|
||||
walletName: walletName,
|
||||
coin: coin,
|
||||
secureStore: secureStorageInterface,
|
||||
client: client,
|
||||
cachedClient: cachedClient,
|
||||
tracker: tracker,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1318,7 +1318,7 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
value: bip39.generateMnemonic(strength: 128));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
|
|
3139
lib/services/coins/ecash/ecash_wallet.dart
Normal file
3139
lib/services/coins/ecash/ecash_wallet.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -350,7 +350,7 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
|
||||
final String mnemonic = bip39.generateMnemonic(strength: 256);
|
||||
final String mnemonic = bip39.generateMnemonic(strength: 128);
|
||||
await _secureStore.write(key: '${_walletId}_mnemonic', value: mnemonic);
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1498,7 +1498,7 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
value: bip39.generateMnemonic(strength: 128));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
|
|
|
@ -12,8 +12,8 @@ import 'package:stackwallet/services/event_bus/events/global/updated_in_backgrou
|
|||
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
|
||||
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/services/mixins/xpubable.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
|
||||
|
@ -252,7 +252,8 @@ class Manager with ChangeNotifier {
|
|||
);
|
||||
}
|
||||
|
||||
bool get hasXPub => _currentWallet is XPubAble;
|
||||
// TODO: re enable once xpubs have been redone
|
||||
bool get hasXPub => false; //_currentWallet is XPubAble;
|
||||
|
||||
Future<String> get xpub async {
|
||||
if (!hasXPub) {
|
||||
|
|
|
@ -1479,7 +1479,7 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
value: bip39.generateMnemonic(strength: 128));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
|
|
|
@ -1394,7 +1394,7 @@ class ParticlWallet extends CoinServiceAPI
|
|||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
value: bip39.generateMnemonic(strength: 128));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
|
|
|
@ -35,9 +35,10 @@ mixin FiroHive {
|
|||
}
|
||||
|
||||
// mintIndex
|
||||
int? firoGetMintIndex() {
|
||||
int firoGetMintIndex() {
|
||||
return DB.instance.get<dynamic>(boxName: _walletId, key: "mintIndex")
|
||||
as int?;
|
||||
as int? ??
|
||||
0;
|
||||
}
|
||||
|
||||
Future<void> firoUpdateMintIndex(int mintIndex) async {
|
||||
|
|
|
@ -89,7 +89,7 @@ class PriceAPI {
|
|||
final uri =
|
||||
Uri.parse("https://api.coingecko.com/api/v3/coins/markets?vs_currency"
|
||||
"=${baseCurrency.toLowerCase()}"
|
||||
"&ids=monero,bitcoin,litecoin,epic-cash,zcoin,dogecoin,"
|
||||
"&ids=monero,bitcoin,litecoin,ecash,epic-cash,zcoin,dogecoin,"
|
||||
"bitcoin-cash,namecoin,wownero,ethereum,particl"
|
||||
"&order=market_cap_desc&per_page=50&page=1&sparkline=false");
|
||||
|
||||
|
|
|
@ -1,38 +1,44 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/isar/stack_theme.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
final coinIconProvider = Provider.family<String, Coin>((ref, coin) {
|
||||
final assets = ref.watch(themeProvider).assets;
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoin;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoin;
|
||||
case Coin.bitcoincash:
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincash;
|
||||
case Coin.dogecoin:
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoin;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCash;
|
||||
case Coin.firo:
|
||||
case Coin.firoTestNet:
|
||||
return assets.firo;
|
||||
case Coin.monero:
|
||||
return assets.monero;
|
||||
case Coin.wownero:
|
||||
return assets.wownero;
|
||||
case Coin.namecoin:
|
||||
return assets.namecoin;
|
||||
case Coin.particl:
|
||||
return assets.particl;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereum;
|
||||
case Coin.nano:
|
||||
return assets.nano;
|
||||
final assets = ref.watch(themeAssetsProvider);
|
||||
|
||||
if (assets is ThemeAssets) {
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoin;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoin;
|
||||
case Coin.bitcoincash:
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincash;
|
||||
case Coin.dogecoin:
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoin;
|
||||
case Coin.eCash:
|
||||
return assets.bitcoin;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCash;
|
||||
case Coin.firo:
|
||||
case Coin.firoTestNet:
|
||||
return assets.firo;
|
||||
case Coin.monero:
|
||||
return assets.monero;
|
||||
case Coin.wownero:
|
||||
return assets.wownero;
|
||||
case Coin.namecoin:
|
||||
return assets.namecoin;
|
||||
case Coin.particl:
|
||||
return assets.particl;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereum;
|
||||
}
|
||||
} else {
|
||||
return (assets as ThemeAssetsV2).coinIcons[coin.mainNetVersion]!;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,77 +1,92 @@
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/isar/stack_theme.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
final coinImageProvider = Provider.family<String, Coin>((ref, coin) {
|
||||
final assets = ref.watch(themeProvider).assets;
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
return assets.bitcoinImage;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoinImage;
|
||||
case Coin.bitcoincash:
|
||||
return assets.bitcoincashImage;
|
||||
case Coin.dogecoin:
|
||||
return assets.dogecoinImage;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCashImage;
|
||||
case Coin.firo:
|
||||
return assets.firoImage;
|
||||
case Coin.monero:
|
||||
return assets.moneroImage;
|
||||
case Coin.wownero:
|
||||
return assets.wowneroImage;
|
||||
case Coin.namecoin:
|
||||
return assets.namecoinImage;
|
||||
case Coin.particl:
|
||||
return assets.particlImage;
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoinImage;
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincashImage;
|
||||
case Coin.firoTestNet:
|
||||
return assets.firoImage;
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoinImage;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereumImage;
|
||||
case Coin.nano:
|
||||
return assets.nano;
|
||||
final assets = ref.watch(themeAssetsProvider);
|
||||
|
||||
if (assets is ThemeAssets) {
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
return assets.bitcoinImage;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoinImage;
|
||||
case Coin.bitcoincash:
|
||||
return assets.bitcoincashImage;
|
||||
case Coin.dogecoin:
|
||||
return assets.dogecoinImage;
|
||||
case Coin.eCash:
|
||||
return assets.bitcoinImage;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCashImage;
|
||||
case Coin.firo:
|
||||
return assets.firoImage;
|
||||
case Coin.monero:
|
||||
return assets.moneroImage;
|
||||
case Coin.wownero:
|
||||
return assets.wowneroImage;
|
||||
case Coin.namecoin:
|
||||
return assets.namecoinImage;
|
||||
case Coin.particl:
|
||||
return assets.particlImage;
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoinImage;
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincashImage;
|
||||
case Coin.firoTestNet:
|
||||
return assets.firoImage;
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoinImage;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereumImage;
|
||||
}
|
||||
} else {
|
||||
return (assets as ThemeAssetsV2).coinImages[coin.mainNetVersion]!;
|
||||
}
|
||||
});
|
||||
|
||||
final coinImageSecondaryProvider = Provider.family<String, Coin>((ref, coin) {
|
||||
final assets = ref.watch(themeProvider).assets;
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoinImageSecondary;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoinImageSecondary;
|
||||
case Coin.bitcoincash:
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincashImageSecondary;
|
||||
case Coin.dogecoin:
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoinImageSecondary;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCashImageSecondary;
|
||||
case Coin.firo:
|
||||
case Coin.firoTestNet:
|
||||
return assets.firoImageSecondary;
|
||||
case Coin.monero:
|
||||
return assets.moneroImageSecondary;
|
||||
case Coin.wownero:
|
||||
return assets.wowneroImageSecondary;
|
||||
case Coin.namecoin:
|
||||
return assets.namecoinImageSecondary;
|
||||
case Coin.particl:
|
||||
return assets.particlImageSecondary;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereumImageSecondary;
|
||||
case Coin.nano:
|
||||
return assets.nano;
|
||||
final assets = ref.watch(themeAssetsProvider);
|
||||
|
||||
if (assets is ThemeAssets) {
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
return assets.bitcoinImageSecondary;
|
||||
case Coin.litecoin:
|
||||
case Coin.litecoinTestNet:
|
||||
return assets.litecoinImageSecondary;
|
||||
case Coin.bitcoincash:
|
||||
return assets.bitcoincashImageSecondary;
|
||||
case Coin.dogecoin:
|
||||
return assets.dogecoinImageSecondary;
|
||||
case Coin.eCash:
|
||||
return assets.bitcoinImageSecondary;
|
||||
case Coin.epicCash:
|
||||
return assets.epicCashImageSecondary;
|
||||
case Coin.firo:
|
||||
return assets.firoImageSecondary;
|
||||
case Coin.monero:
|
||||
return assets.moneroImageSecondary;
|
||||
case Coin.wownero:
|
||||
return assets.wowneroImageSecondary;
|
||||
case Coin.namecoin:
|
||||
return assets.namecoinImageSecondary;
|
||||
case Coin.particl:
|
||||
return assets.particlImageSecondary;
|
||||
case Coin.bitcoinTestNet:
|
||||
return assets.bitcoinImageSecondary;
|
||||
case Coin.bitcoincashTestnet:
|
||||
return assets.bitcoincashImageSecondary;
|
||||
case Coin.firoTestNet:
|
||||
return assets.firoImageSecondary;
|
||||
case Coin.dogecoinTestNet:
|
||||
return assets.dogecoinImageSecondary;
|
||||
case Coin.ethereum:
|
||||
return assets.ethereumImageSecondary;
|
||||
}
|
||||
} else {
|
||||
return (assets as ThemeAssetsV2).coinSecondaryImages[coin.mainNetVersion]!;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ class CoinThemeColorDefault {
|
|||
Color get firo => const Color(0xFFFF897A);
|
||||
Color get dogecoin => const Color(0xFFFFE079);
|
||||
Color get epicCash => const Color(0xFFC5C7CB);
|
||||
Color get eCash => const Color(0xFFC5C7CB);
|
||||
Color get ethereum => const Color(0xFFA7ADE9);
|
||||
Color get monero => const Color(0xFFFF9E6B);
|
||||
Color get namecoin => const Color(0xFF91B1E1);
|
||||
|
@ -33,6 +34,8 @@ class CoinThemeColorDefault {
|
|||
case Coin.dogecoin:
|
||||
case Coin.dogecoinTestNet:
|
||||
return dogecoin;
|
||||
case Coin.eCash:
|
||||
return eCash;
|
||||
case Coin.epicCash:
|
||||
return epicCash;
|
||||
case Coin.ethereum:
|
||||
|
|
|
@ -103,6 +103,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
// icons
|
||||
final Color bottomNavIconBack;
|
||||
final Color bottomNavIconIcon;
|
||||
final Color bottomNavIconIconHighlighted;
|
||||
final Color topNavIconPrimary;
|
||||
final Color topNavIconGreen;
|
||||
final Color topNavIconYellow;
|
||||
|
@ -281,6 +282,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
required this.snackBarTextInfo,
|
||||
required this.bottomNavIconBack,
|
||||
required this.bottomNavIconIcon,
|
||||
required this.bottomNavIconIconHighlighted,
|
||||
required this.topNavIconPrimary,
|
||||
required this.topNavIconGreen,
|
||||
required this.topNavIconYellow,
|
||||
|
@ -441,6 +443,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
snackBarTextInfo: colorTheme.snackBarTextInfo,
|
||||
bottomNavIconBack: colorTheme.bottomNavIconBack,
|
||||
bottomNavIconIcon: colorTheme.bottomNavIconIcon,
|
||||
bottomNavIconIconHighlighted: colorTheme.bottomNavIconIconHighlighted,
|
||||
topNavIconPrimary: colorTheme.topNavIconPrimary,
|
||||
topNavIconGreen: colorTheme.topNavIconGreen,
|
||||
topNavIconYellow: colorTheme.topNavIconYellow,
|
||||
|
@ -603,6 +606,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
Color? snackBarTextInfo,
|
||||
Color? bottomNavIconBack,
|
||||
Color? bottomNavIconIcon,
|
||||
Color? bottomNavIconIconHighlighted,
|
||||
Color? topNavIconPrimary,
|
||||
Color? topNavIconGreen,
|
||||
Color? topNavIconYellow,
|
||||
|
@ -776,6 +780,8 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
snackBarTextInfo: snackBarTextInfo ?? this.snackBarTextInfo,
|
||||
bottomNavIconBack: bottomNavIconBack ?? this.bottomNavIconBack,
|
||||
bottomNavIconIcon: bottomNavIconIcon ?? this.bottomNavIconIcon,
|
||||
bottomNavIconIconHighlighted:
|
||||
bottomNavIconIconHighlighted ?? this.bottomNavIconIconHighlighted,
|
||||
topNavIconPrimary: topNavIconPrimary ?? this.topNavIconPrimary,
|
||||
topNavIconGreen: topNavIconGreen ?? this.topNavIconGreen,
|
||||
topNavIconYellow: topNavIconYellow ?? this.topNavIconYellow,
|
||||
|
@ -1279,6 +1285,11 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
other.bottomNavIconIcon,
|
||||
t,
|
||||
)!,
|
||||
bottomNavIconIconHighlighted: Color.lerp(
|
||||
bottomNavIconIconHighlighted,
|
||||
other.bottomNavIconIconHighlighted,
|
||||
t,
|
||||
)!,
|
||||
topNavIconPrimary: Color.lerp(
|
||||
topNavIconPrimary,
|
||||
other.topNavIconPrimary,
|
||||
|
@ -1671,6 +1682,8 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
return _coin.dogecoin;
|
||||
case Coin.epicCash:
|
||||
return _coin.epicCash;
|
||||
case Coin.eCash:
|
||||
return _coin.eCash;
|
||||
case Coin.ethereum:
|
||||
return _coin.ethereum;
|
||||
case Coin.firo:
|
||||
|
|
|
@ -20,3 +20,11 @@ final themeProvider = StateProvider<StackTheme>(
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
final themeAssetsProvider = StateProvider<IThemeAssets>(
|
||||
(ref) => ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:archive/archive_io.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
@ -17,6 +17,7 @@ final pThemeService = Provider<ThemeService>((ref) {
|
|||
});
|
||||
|
||||
class ThemeService {
|
||||
static const _currentDefaultThemeVersion = 2;
|
||||
ThemeService._();
|
||||
static ThemeService? _instance;
|
||||
static ThemeService get instance => _instance ??= ThemeService._();
|
||||
|
@ -92,6 +93,70 @@ class ThemeService {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> checkDefaultThemesOnStartup() async {
|
||||
// install default themes
|
||||
if (!(await ThemeService.instance.verifyInstalled(themeId: "light"))) {
|
||||
Logging.instance.log(
|
||||
"Installing default light theme...",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
final lightZip = await rootBundle.load("assets/default_themes/light.zip");
|
||||
await ThemeService.instance
|
||||
.install(themeArchiveData: lightZip.buffer.asUint8List());
|
||||
Logging.instance.log(
|
||||
"Installing default light theme... finished",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
} else {
|
||||
// check installed version
|
||||
final theme = ThemeService.instance.getTheme(themeId: "light");
|
||||
if ((theme?.version ?? 1) < _currentDefaultThemeVersion) {
|
||||
Logging.instance.log(
|
||||
"Updating default light theme...",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
final lightZip =
|
||||
await rootBundle.load("assets/default_themes/light.zip");
|
||||
await ThemeService.instance
|
||||
.install(themeArchiveData: lightZip.buffer.asUint8List());
|
||||
Logging.instance.log(
|
||||
"Updating default light theme... finished",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(await ThemeService.instance.verifyInstalled(themeId: "dark"))) {
|
||||
Logging.instance.log(
|
||||
"Installing default dark theme... ",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
final darkZip = await rootBundle.load("assets/default_themes/dark.zip");
|
||||
await ThemeService.instance
|
||||
.install(themeArchiveData: darkZip.buffer.asUint8List());
|
||||
Logging.instance.log(
|
||||
"Installing default dark theme... finished",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
} else {
|
||||
// check installed version
|
||||
final theme = ThemeService.instance.getTheme(themeId: "dark");
|
||||
if ((theme?.version ?? 1) < _currentDefaultThemeVersion) {
|
||||
Logging.instance.log(
|
||||
"Updating default dark theme...",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
final darkZip = await rootBundle.load("assets/default_themes/dark.zip");
|
||||
await ThemeService.instance
|
||||
.install(themeArchiveData: darkZip.buffer.asUint8List());
|
||||
Logging.instance.log(
|
||||
"Updating default dark theme... finished",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO more thorough check/verification of theme
|
||||
Future<bool> verifyInstalled({required String themeId}) async {
|
||||
final dbHasTheme =
|
||||
|
@ -175,6 +240,7 @@ class ThemeService {
|
|||
class StackThemeMetaData {
|
||||
final String name;
|
||||
final String id;
|
||||
final int version;
|
||||
final String sha256;
|
||||
final String size;
|
||||
final String previewImageUrl;
|
||||
|
@ -182,6 +248,7 @@ class StackThemeMetaData {
|
|||
StackThemeMetaData({
|
||||
required this.name,
|
||||
required this.id,
|
||||
required this.version,
|
||||
required this.sha256,
|
||||
required this.size,
|
||||
required this.previewImageUrl,
|
||||
|
@ -192,6 +259,7 @@ class StackThemeMetaData {
|
|||
return StackThemeMetaData(
|
||||
name: map["name"] as String,
|
||||
id: map["id"] as String,
|
||||
version: map["version"] as int? ?? 1,
|
||||
sha256: map["sha256"] as String,
|
||||
size: map["size"] as String,
|
||||
previewImageUrl: map["previewImageUrl"] as String,
|
||||
|
@ -210,6 +278,7 @@ class StackThemeMetaData {
|
|||
return "$runtimeType("
|
||||
"name: $name, "
|
||||
"id: $id, "
|
||||
"version: $version, "
|
||||
"sha256: $sha256, "
|
||||
"size: $size, "
|
||||
"previewImageUrl: $previewImageUrl"
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:flutter_libepiccash/epic_cash.dart';
|
|||
import 'package:nanodart/nanodart.dart';
|
||||
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/ecash/ecash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/litecoin/litecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
|
||||
|
@ -62,6 +63,8 @@ class AddressUtils {
|
|||
return true; //TODO - validate ETH address
|
||||
case Coin.firo:
|
||||
return Address.validateAddress(address, firoNetwork);
|
||||
case Coin.eCash:
|
||||
return Address.validateAddress(address, eCashNetwork);
|
||||
case Coin.monero:
|
||||
return RegExp("[a-zA-Z0-9]{95}").hasMatch(address) ||
|
||||
RegExp("[a-zA-Z0-9]{106}").hasMatch(address);
|
||||
|
|
|
@ -165,6 +165,7 @@ class _SVG {
|
|||
String get questionMessage => "assets/svg/message-question.svg";
|
||||
String get envelope => "assets/svg/envelope.svg";
|
||||
String get share => "assets/svg/share-2.svg";
|
||||
String get recycle => "assets/svg/anonymize.svg";
|
||||
String get anonymize => "assets/svg/tx-icon-anonymize.svg";
|
||||
String get anonymizePending => "assets/svg/tx-icon-anonymize-pending.svg";
|
||||
String get anonymizeFailed => "assets/svg/tx-icon-anonymize-failed.svg";
|
||||
|
@ -193,7 +194,7 @@ class _SVG {
|
|||
String get exchange3 => "assets/svg/exchange-3.svg";
|
||||
String get messageQuestion => "assets/svg/message-question-1.svg";
|
||||
String get list => "assets/svg/list-ul.svg";
|
||||
String get unclaimedPaynym => "assets/svg/unclaimed.png";
|
||||
String get unclaimedPaynym => "assets/svg/unclaimed.svg";
|
||||
|
||||
String get trocadorRatingA => "assets/svg/trocador_rating_a.svg";
|
||||
String get trocadorRatingB => "assets/svg/trocador_rating_b.svg";
|
||||
|
|
|
@ -17,6 +17,8 @@ Uri getDefaultBlockExplorerUrlFor({
|
|||
return Uri.parse("https://mempool.space/testnet/tx/$txid");
|
||||
case Coin.dogecoin:
|
||||
return Uri.parse("https://chain.so/tx/DOGE/$txid");
|
||||
case Coin.eCash:
|
||||
return Uri.parse("https://explorer.bitcoinabc.org/tx/$txid");
|
||||
case Coin.dogecoinTestNet:
|
||||
return Uri.parse("https://chain.so/tx/DOGETEST/$txid");
|
||||
case Coin.epicCash:
|
||||
|
|
|
@ -25,6 +25,7 @@ abstract class Constants {
|
|||
// static bool enableBuy = enableExchange;
|
||||
// // true; // true for development,
|
||||
|
||||
static const BigInt _satsPerCoinECash = BigInt.from(100);
|
||||
static final BigInt _satsPerCoinEthereum = BigInt.from(1000000000000000000);
|
||||
static final BigInt _satsPerCoinMonero = BigInt.from(1000000000000);
|
||||
static final BigInt _satsPerCoinWownero = BigInt.from(100000000000);
|
||||
|
@ -35,6 +36,7 @@ abstract class Constants {
|
|||
static const int _decimalPlacesWownero = 11;
|
||||
static const int _decimalPlacesMonero = 12;
|
||||
static const int _decimalPlacesEthereum = 18;
|
||||
static const int _decimalPlacesECash = 2;
|
||||
|
||||
static const int notificationsMax = 0xFFFFFFFF;
|
||||
static const Duration networkAliveTimerDuration = Duration(seconds: 10);
|
||||
|
@ -44,7 +46,7 @@ abstract class Constants {
|
|||
// Enable Logger.print statements
|
||||
static const bool disableLogger = false;
|
||||
|
||||
static const int currentHiveDbVersion = 8;
|
||||
static const int currentDataVersion = 10;
|
||||
|
||||
static const int rescanV1 = 1;
|
||||
|
||||
|
@ -76,6 +78,9 @@ abstract class Constants {
|
|||
|
||||
case Coin.ethereum:
|
||||
return _satsPerCoinEthereum;
|
||||
|
||||
case Coin.eCash:
|
||||
return _satsPerCoinECash;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +112,9 @@ abstract class Constants {
|
|||
|
||||
case Coin.ethereum:
|
||||
return _decimalPlacesEthereum;
|
||||
|
||||
case Coin.eCash:
|
||||
return _decimalPlacesECash;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,6 +131,7 @@ abstract class Constants {
|
|||
case Coin.bitcoinTestNet:
|
||||
case Coin.dogecoinTestNet:
|
||||
case Coin.firoTestNet:
|
||||
case Coin.eCash:
|
||||
case Coin.epicCash:
|
||||
case Coin.ethereum:
|
||||
case Coin.namecoin:
|
||||
|
@ -146,10 +155,9 @@ abstract class Constants {
|
|||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
case Coin.bitcoinTestNet:
|
||||
return 600;
|
||||
|
||||
case Coin.bitcoincash:
|
||||
case Coin.bitcoincashTestnet:
|
||||
case Coin.eCash:
|
||||
return 600;
|
||||
|
||||
case Coin.dogecoin:
|
||||
|
@ -187,7 +195,7 @@ abstract class Constants {
|
|||
}
|
||||
}
|
||||
|
||||
static const int seedPhraseWordCountBip39 = 24;
|
||||
static const int seedPhraseWordCountBip39 = 12;
|
||||
static const int seedPhraseWordCountMonero = 25;
|
||||
|
||||
static const Map<int, String> monthMapShort = {
|
||||
|
|
|
@ -3,9 +3,12 @@ import 'package:isar/isar.dart';
|
|||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart'
|
||||
as isar_contact;
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
|
||||
import 'package:stackwallet/models/models.dart';
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
|
@ -290,6 +293,48 @@ class DbVersionMigrator with WalletDB {
|
|||
// try to continue migrating
|
||||
return await migrate(8, secureStore: secureStore);
|
||||
|
||||
case 8:
|
||||
// migrate
|
||||
await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
|
||||
final walletsService =
|
||||
WalletsService(secureStorageInterface: secureStore);
|
||||
final walletInfoList = await walletsService.walletNames;
|
||||
await MainDB.instance.initMainDB();
|
||||
for (final walletId in walletInfoList.keys) {
|
||||
final info = walletInfoList[walletId]!;
|
||||
if (info.coin == Coin.bitcoincash ||
|
||||
info.coin == Coin.bitcoincashTestnet) {
|
||||
final ids = await MainDB.instance
|
||||
.getAddresses(walletId)
|
||||
.filter()
|
||||
.typeEqualTo(isar_models.AddressType.p2sh)
|
||||
.idProperty()
|
||||
.findAll();
|
||||
|
||||
await MainDB.instance.isar.writeTxn(() async {
|
||||
await MainDB.instance.isar.addresses.deleteAll(ids);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// update version
|
||||
await DB.instance.put<dynamic>(
|
||||
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 9);
|
||||
|
||||
// try to continue migrating
|
||||
return await migrate(9, secureStore: secureStore);
|
||||
|
||||
case 9:
|
||||
// migrate
|
||||
await _v9();
|
||||
|
||||
// update version
|
||||
await DB.instance.put<dynamic>(
|
||||
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 10);
|
||||
|
||||
// try to continue migrating
|
||||
return await migrate(10, secureStore: secureStore);
|
||||
|
||||
default:
|
||||
// finally return
|
||||
return;
|
||||
|
@ -447,4 +492,50 @@ class DbVersionMigrator with WalletDB {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _v9() async {
|
||||
final addressBookBox = await Hive.openBox<dynamic>(DB.boxNameAddressBook);
|
||||
await MainDB.instance.initMainDB();
|
||||
|
||||
final keys = List<String>.from(addressBookBox.keys);
|
||||
final contacts = keys
|
||||
.map((id) => Contact.fromJson(
|
||||
Map<String, dynamic>.from(
|
||||
addressBookBox.get(id) as Map,
|
||||
),
|
||||
))
|
||||
.toList(growable: false);
|
||||
|
||||
final List<isar_contact.ContactEntry> newContacts = [];
|
||||
|
||||
for (final contact in contacts) {
|
||||
final List<isar_contact.ContactAddressEntry> newContactAddressEntries =
|
||||
[];
|
||||
|
||||
for (final entry in contact.addresses) {
|
||||
newContactAddressEntries.add(
|
||||
isar_contact.ContactAddressEntry()
|
||||
..coinName = entry.coin.name
|
||||
..address = entry.address
|
||||
..label = entry.label
|
||||
..other = entry.other,
|
||||
);
|
||||
}
|
||||
|
||||
final newContact = isar_contact.ContactEntry(
|
||||
name: contact.name,
|
||||
addresses: newContactAddressEntries,
|
||||
isFavorite: contact.isFavorite,
|
||||
customId: contact.id,
|
||||
);
|
||||
|
||||
newContacts.add(newContact);
|
||||
}
|
||||
|
||||
await MainDB.instance.isar.writeTxn(() async {
|
||||
await MainDB.instance.isar.contactEntrys.putAll(newContacts);
|
||||
});
|
||||
|
||||
await addressBookBox.deleteFromDisk();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
// import 'package:web3dart/browser.dart';
|
||||
|
||||
abstract class DefaultNodes {
|
||||
static const String defaultNodeIdPrefix = "default_";
|
||||
|
@ -13,6 +12,7 @@ abstract class DefaultNodes {
|
|||
dogecoin,
|
||||
firo,
|
||||
monero,
|
||||
eCash,
|
||||
epicCash,
|
||||
ethereum,
|
||||
bitcoincash,
|
||||
|
@ -231,6 +231,18 @@ abstract class DefaultNodes {
|
|||
isDown: false,
|
||||
);
|
||||
|
||||
static NodeModel get eCash => NodeModel(
|
||||
host: "electrum.bitcoinabc.org",
|
||||
port: 50002,
|
||||
name: defaultName,
|
||||
id: _nodeId(Coin.eCash),
|
||||
useSSL: true,
|
||||
enabled: true,
|
||||
coinName: Coin.eCash.name,
|
||||
isFailover: true,
|
||||
isDown: false,
|
||||
);
|
||||
|
||||
static NodeModel getNodeFor(Coin coin) {
|
||||
switch (coin) {
|
||||
case Coin.bitcoin:
|
||||
|
@ -245,6 +257,9 @@ abstract class DefaultNodes {
|
|||
case Coin.dogecoin:
|
||||
return dogecoin;
|
||||
|
||||
case Coin.eCash:
|
||||
return eCash;
|
||||
|
||||
case Coin.epicCash:
|
||||
return epicCash;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart'
|
|||
as bch;
|
||||
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'
|
||||
as doge;
|
||||
import 'package:stackwallet/services/coins/ecash/ecash_wallet.dart' as ecash;
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart'
|
||||
as epic;
|
||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart'
|
||||
|
@ -23,6 +24,7 @@ enum Coin {
|
|||
bitcoin,
|
||||
bitcoincash,
|
||||
dogecoin,
|
||||
eCash,
|
||||
epicCash,
|
||||
ethereum,
|
||||
firo,
|
||||
|
@ -61,6 +63,8 @@ extension CoinExt on Coin {
|
|||
return "Dogecoin";
|
||||
case Coin.epicCash:
|
||||
return "Epic Cash";
|
||||
case Coin.eCash:
|
||||
return "E-Cash";
|
||||
case Coin.ethereum:
|
||||
return "Ethereum";
|
||||
case Coin.firo:
|
||||
|
@ -102,6 +106,8 @@ extension CoinExt on Coin {
|
|||
return "EPIC";
|
||||
case Coin.ethereum:
|
||||
return "ETH";
|
||||
case Coin.eCash:
|
||||
return "XEC";
|
||||
case Coin.firo:
|
||||
return "FIRO";
|
||||
case Coin.monero:
|
||||
|
@ -142,6 +148,8 @@ extension CoinExt on Coin {
|
|||
return "epic";
|
||||
case Coin.ethereum:
|
||||
return "ethereum";
|
||||
case Coin.eCash:
|
||||
return "ecash";
|
||||
case Coin.firo:
|
||||
return "firo";
|
||||
case Coin.monero:
|
||||
|
@ -181,6 +189,7 @@ extension CoinExt on Coin {
|
|||
case Coin.bitcoincashTestnet:
|
||||
case Coin.firoTestNet:
|
||||
case Coin.dogecoinTestNet:
|
||||
case Coin.eCash:
|
||||
return true;
|
||||
|
||||
case Coin.epicCash:
|
||||
|
@ -204,6 +213,7 @@ extension CoinExt on Coin {
|
|||
case Coin.firo:
|
||||
case Coin.namecoin:
|
||||
case Coin.particl:
|
||||
case Coin.eCash:
|
||||
case Coin.epicCash:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
|
@ -231,6 +241,7 @@ extension CoinExt on Coin {
|
|||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
case Coin.nano:
|
||||
case Coin.eCash:
|
||||
return false;
|
||||
|
||||
case Coin.dogecoinTestNet:
|
||||
|
@ -256,6 +267,7 @@ extension CoinExt on Coin {
|
|||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
case Coin.nano:
|
||||
case Coin.eCash:
|
||||
return this;
|
||||
|
||||
case Coin.dogecoinTestNet:
|
||||
|
@ -300,6 +312,9 @@ extension CoinExt on Coin {
|
|||
case Coin.epicCash:
|
||||
return epic.MINIMUM_CONFIRMATIONS;
|
||||
|
||||
case Coin.eCash:
|
||||
return ecash.MINIMUM_CONFIRMATIONS;
|
||||
|
||||
case Coin.ethereum:
|
||||
return eth.MINIMUM_CONFIRMATIONS;
|
||||
|
||||
|
@ -354,6 +369,11 @@ Coin coinFromPrettyName(String name) {
|
|||
case "firo":
|
||||
return Coin.firo;
|
||||
|
||||
case "E-Cash":
|
||||
case "ecash":
|
||||
case "eCash":
|
||||
return Coin.eCash;
|
||||
|
||||
case "Monero":
|
||||
case "monero":
|
||||
return Coin.monero;
|
||||
|
@ -423,6 +443,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) {
|
|||
return Coin.dogecoin;
|
||||
case "epic":
|
||||
return Coin.epicCash;
|
||||
case "xec":
|
||||
return Coin.eCash;
|
||||
case "eth":
|
||||
return Coin.ethereum;
|
||||
case "firo":
|
||||
|
|
|
@ -6,6 +6,7 @@ enum DerivePathType {
|
|||
bip49,
|
||||
bip84,
|
||||
eth,
|
||||
eCash44,
|
||||
}
|
||||
|
||||
extension DerivePathTypeExt on DerivePathType {
|
||||
|
@ -27,6 +28,9 @@ extension DerivePathTypeExt on DerivePathType {
|
|||
case Coin.particl:
|
||||
return DerivePathType.bip84;
|
||||
|
||||
case Coin.eCash:
|
||||
return DerivePathType.eCash44;
|
||||
|
||||
case Coin.ethereum: // TODO: do we need something here?
|
||||
return DerivePathType.eth;
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
|
@ -50,4 +52,15 @@ abstract class Util {
|
|||
}
|
||||
return MaterialColor(color.value, swatch);
|
||||
}
|
||||
|
||||
static void printJson(dynamic json) {
|
||||
if (json is Map || json is List) {
|
||||
final spaces = ' ' * 4;
|
||||
final encoder = JsonEncoder.withIndent(spaces);
|
||||
final pretty = encoder.convert(json);
|
||||
log(pretty);
|
||||
} else {
|
||||
log(dynamic.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -14,8 +17,6 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
|
|||
import 'package:stackwallet/widgets/expandable.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
import '../themes/theme_providers.dart';
|
||||
|
||||
class AddressBookCard extends ConsumerStatefulWidget {
|
||||
const AddressBookCard({
|
||||
Key? key,
|
||||
|
@ -48,7 +49,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// provider hack to prevent trying to update widget with deleted contact
|
||||
Contact? _contact;
|
||||
ContactEntry? _contact;
|
||||
try {
|
||||
_contact = ref.watch(addressBookServiceProvider
|
||||
.select((value) => value.getContactById(contactId)));
|
||||
|
@ -81,7 +82,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
|
|||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: contact.id == "default"
|
||||
color: contact.customId == "default"
|
||||
? Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.myStackContactIconBG
|
||||
|
@ -90,12 +91,14 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
|
|||
.textFieldDefaultBG,
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
child: contact.id == "default"
|
||||
child: contact.customId == "default"
|
||||
? Center(
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 20,
|
||||
|
@ -176,7 +179,7 @@ class _AddressBookCardState extends ConsumerState<AddressBookCard> {
|
|||
useSafeArea: true,
|
||||
barrierDismissible: true,
|
||||
builder: (_) => ContactPopUp(
|
||||
contactId: contact.id,
|
||||
contactId: contact.customId,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
@ -47,10 +49,12 @@ class _LivingStackIconState extends ConsumerState<LivingStackIcon> {
|
|||
child: AnimatedScale(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
scale: _hovering ? 1.2 : 1,
|
||||
child: SvgPicture.asset(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.stackIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -46,6 +46,12 @@ class RoundedContainer extends StatelessWidget {
|
|||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius * radiusMultiplier,
|
||||
),
|
||||
side: borderColor == null
|
||||
? BorderSide.none
|
||||
: BorderSide(
|
||||
color: borderColor!,
|
||||
width: 1.2,
|
||||
),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: child,
|
||||
|
|
|
@ -24,7 +24,7 @@ class TradeCard extends ConsumerWidget {
|
|||
final Trade trade;
|
||||
final VoidCallback onTap;
|
||||
|
||||
String _fetchIconAssetForStatus(String statusString, ThemeAssets assets) {
|
||||
String _fetchIconAssetForStatus(String statusString, IThemeAssets assets) {
|
||||
ChangeNowTransactionStatus? status;
|
||||
try {
|
||||
if (statusString.toLowerCase().startsWith("waiting")) {
|
||||
|
@ -89,11 +89,7 @@ class TradeCard extends ConsumerWidget {
|
|||
File(
|
||||
_fetchIconAssetForStatus(
|
||||
trade.status,
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets,
|
||||
),
|
||||
),
|
||||
ref.watch(themeAssetsProvider),
|
||||
),
|
||||
),
|
||||
width: 32,
|
||||
|
|
|
@ -14,7 +14,7 @@ class ExchangeNavIcon extends ConsumerWidget {
|
|||
File(
|
||||
ref.watch(
|
||||
themeProvider.select(
|
||||
(value) => value.assets.buy,
|
||||
(value) => value.assets.exchange,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -68,9 +68,10 @@ class WalletNavigationBarItem extends ConsumerWidget {
|
|||
Text(
|
||||
data.label ?? "",
|
||||
style: STextStyles.buttonSmall(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavText),
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavText,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -112,7 +113,11 @@ class WalletNavigationBarMoreItem extends ConsumerWidget {
|
|||
child: Text(
|
||||
data.label ?? "",
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.buttonSmall(context),
|
||||
style: STextStyles.buttonSmall(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavText,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue