> allOffsets,
+) {
+ final object = Ordinal(
+ content: reader.readString(offsets[0]),
+ inscriptionId: reader.readString(offsets[1]),
+ inscriptionNumber: reader.readLong(offsets[2]),
+ utxoTXID: reader.readString(offsets[3]),
+ utxoVOUT: reader.readLong(offsets[4]),
+ walletId: reader.readString(offsets[5]),
+ );
+ object.id = id;
+ return object;
+}
+
+P _ordinalDeserializeProp(
+ IsarReader reader,
+ int propertyId,
+ int offset,
+ Map> allOffsets,
+) {
+ switch (propertyId) {
+ case 0:
+ return (reader.readString(offset)) as P;
+ case 1:
+ return (reader.readString(offset)) as P;
+ case 2:
+ return (reader.readLong(offset)) as P;
+ case 3:
+ return (reader.readString(offset)) as P;
+ case 4:
+ return (reader.readLong(offset)) as P;
+ case 5:
+ return (reader.readString(offset)) as P;
+ default:
+ throw IsarError('Unknown property with id $propertyId');
+ }
+}
+
+Id _ordinalGetId(Ordinal object) {
+ return object.id;
+}
+
+List> _ordinalGetLinks(Ordinal object) {
+ return [];
+}
+
+void _ordinalAttach(IsarCollection col, Id id, Ordinal object) {
+ object.id = id;
+}
+
+extension OrdinalByIndex on IsarCollection {
+ Future getByInscriptionIdUtxoTXIDUtxoVOUT(
+ String inscriptionId, String utxoTXID, int utxoVOUT) {
+ return getByIndex(r'inscriptionId_utxoTXID_utxoVOUT',
+ [inscriptionId, utxoTXID, utxoVOUT]);
+ }
+
+ Ordinal? getByInscriptionIdUtxoTXIDUtxoVOUTSync(
+ String inscriptionId, String utxoTXID, int utxoVOUT) {
+ return getByIndexSync(r'inscriptionId_utxoTXID_utxoVOUT',
+ [inscriptionId, utxoTXID, utxoVOUT]);
+ }
+
+ Future deleteByInscriptionIdUtxoTXIDUtxoVOUT(
+ String inscriptionId, String utxoTXID, int utxoVOUT) {
+ return deleteByIndex(r'inscriptionId_utxoTXID_utxoVOUT',
+ [inscriptionId, utxoTXID, utxoVOUT]);
+ }
+
+ bool deleteByInscriptionIdUtxoTXIDUtxoVOUTSync(
+ String inscriptionId, String utxoTXID, int utxoVOUT) {
+ return deleteByIndexSync(r'inscriptionId_utxoTXID_utxoVOUT',
+ [inscriptionId, utxoTXID, utxoVOUT]);
+ }
+
+ Future> getAllByInscriptionIdUtxoTXIDUtxoVOUT(
+ List inscriptionIdValues,
+ List utxoTXIDValues,
+ List utxoVOUTValues) {
+ final len = inscriptionIdValues.length;
+ assert(utxoTXIDValues.length == len && utxoVOUTValues.length == len,
+ 'All index values must have the same length');
+ final values = >[];
+ for (var i = 0; i < len; i++) {
+ values
+ .add([inscriptionIdValues[i], utxoTXIDValues[i], utxoVOUTValues[i]]);
+ }
+
+ return getAllByIndex(r'inscriptionId_utxoTXID_utxoVOUT', values);
+ }
+
+ List getAllByInscriptionIdUtxoTXIDUtxoVOUTSync(
+ List inscriptionIdValues,
+ List utxoTXIDValues,
+ List utxoVOUTValues) {
+ final len = inscriptionIdValues.length;
+ assert(utxoTXIDValues.length == len && utxoVOUTValues.length == len,
+ 'All index values must have the same length');
+ final values = >[];
+ for (var i = 0; i < len; i++) {
+ values
+ .add([inscriptionIdValues[i], utxoTXIDValues[i], utxoVOUTValues[i]]);
+ }
+
+ return getAllByIndexSync(r'inscriptionId_utxoTXID_utxoVOUT', values);
+ }
+
+ Future deleteAllByInscriptionIdUtxoTXIDUtxoVOUT(
+ List inscriptionIdValues,
+ List utxoTXIDValues,
+ List utxoVOUTValues) {
+ final len = inscriptionIdValues.length;
+ assert(utxoTXIDValues.length == len && utxoVOUTValues.length == len,
+ 'All index values must have the same length');
+ final values = >[];
+ for (var i = 0; i < len; i++) {
+ values
+ .add([inscriptionIdValues[i], utxoTXIDValues[i], utxoVOUTValues[i]]);
+ }
+
+ return deleteAllByIndex(r'inscriptionId_utxoTXID_utxoVOUT', values);
+ }
+
+ int deleteAllByInscriptionIdUtxoTXIDUtxoVOUTSync(
+ List inscriptionIdValues,
+ List utxoTXIDValues,
+ List utxoVOUTValues) {
+ final len = inscriptionIdValues.length;
+ assert(utxoTXIDValues.length == len && utxoVOUTValues.length == len,
+ 'All index values must have the same length');
+ final values = >[];
+ for (var i = 0; i < len; i++) {
+ values
+ .add([inscriptionIdValues[i], utxoTXIDValues[i], utxoVOUTValues[i]]);
+ }
+
+ return deleteAllByIndexSync(r'inscriptionId_utxoTXID_utxoVOUT', values);
+ }
+
+ Future putByInscriptionIdUtxoTXIDUtxoVOUT(Ordinal object) {
+ return putByIndex(r'inscriptionId_utxoTXID_utxoVOUT', object);
+ }
+
+ Id putByInscriptionIdUtxoTXIDUtxoVOUTSync(Ordinal object,
+ {bool saveLinks = true}) {
+ return putByIndexSync(r'inscriptionId_utxoTXID_utxoVOUT', object,
+ saveLinks: saveLinks);
+ }
+
+ Future> putAllByInscriptionIdUtxoTXIDUtxoVOUT(
+ List objects) {
+ return putAllByIndex(r'inscriptionId_utxoTXID_utxoVOUT', objects);
+ }
+
+ List putAllByInscriptionIdUtxoTXIDUtxoVOUTSync(List objects,
+ {bool saveLinks = true}) {
+ return putAllByIndexSync(r'inscriptionId_utxoTXID_utxoVOUT', objects,
+ saveLinks: saveLinks);
+ }
+}
+
+extension OrdinalQueryWhereSort on QueryBuilder {
+ QueryBuilder anyId() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(const IdWhereClause.any());
+ });
+ }
+}
+
+extension OrdinalQueryWhere on QueryBuilder {
+ QueryBuilder idEqualTo(Id id) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IdWhereClause.between(
+ lower: id,
+ upper: id,
+ ));
+ });
+ }
+
+ QueryBuilder idNotEqualTo(Id id) {
+ return QueryBuilder.apply(this, (query) {
+ if (query.whereSort == Sort.asc) {
+ return query
+ .addWhereClause(
+ IdWhereClause.lessThan(upper: id, includeUpper: false),
+ )
+ .addWhereClause(
+ IdWhereClause.greaterThan(lower: id, includeLower: false),
+ );
+ } else {
+ return query
+ .addWhereClause(
+ IdWhereClause.greaterThan(lower: id, includeLower: false),
+ )
+ .addWhereClause(
+ IdWhereClause.lessThan(upper: id, includeUpper: false),
+ );
+ }
+ });
+ }
+
+ QueryBuilder idGreaterThan(Id id,
+ {bool include = false}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(
+ IdWhereClause.greaterThan(lower: id, includeLower: include),
+ );
+ });
+ }
+
+ QueryBuilder idLessThan(Id id,
+ {bool include = false}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(
+ IdWhereClause.lessThan(upper: id, includeUpper: include),
+ );
+ });
+ }
+
+ QueryBuilder idBetween(
+ Id lowerId,
+ Id upperId, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IdWhereClause.between(
+ lower: lowerId,
+ includeLower: includeLower,
+ upper: upperId,
+ includeUpper: includeUpper,
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdEqualToAnyUtxoTXIDUtxoVOUT(String inscriptionId) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IndexWhereClause.equalTo(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ value: [inscriptionId],
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdNotEqualToAnyUtxoTXIDUtxoVOUT(String inscriptionId) {
+ return QueryBuilder.apply(this, (query) {
+ if (query.whereSort == Sort.asc) {
+ return query
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [],
+ upper: [inscriptionId],
+ includeUpper: false,
+ ))
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId],
+ includeLower: false,
+ upper: [],
+ ));
+ } else {
+ return query
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId],
+ includeLower: false,
+ upper: [],
+ ))
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [],
+ upper: [inscriptionId],
+ includeUpper: false,
+ ));
+ }
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdUtxoTXIDEqualToAnyUtxoVOUT(
+ String inscriptionId, String utxoTXID) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IndexWhereClause.equalTo(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ value: [inscriptionId, utxoTXID],
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdEqualToUtxoTXIDNotEqualToAnyUtxoVOUT(
+ String inscriptionId, String utxoTXID) {
+ return QueryBuilder.apply(this, (query) {
+ if (query.whereSort == Sort.asc) {
+ return query
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId],
+ upper: [inscriptionId, utxoTXID],
+ includeUpper: false,
+ ))
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID],
+ includeLower: false,
+ upper: [inscriptionId],
+ ));
+ } else {
+ return query
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID],
+ includeLower: false,
+ upper: [inscriptionId],
+ ))
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId],
+ upper: [inscriptionId, utxoTXID],
+ includeUpper: false,
+ ));
+ }
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdUtxoTXIDUtxoVOUTEqualTo(
+ String inscriptionId, String utxoTXID, int utxoVOUT) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IndexWhereClause.equalTo(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ value: [inscriptionId, utxoTXID, utxoVOUT],
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdUtxoTXIDEqualToUtxoVOUTNotEqualTo(
+ String inscriptionId, String utxoTXID, int utxoVOUT) {
+ return QueryBuilder.apply(this, (query) {
+ if (query.whereSort == Sort.asc) {
+ return query
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID],
+ upper: [inscriptionId, utxoTXID, utxoVOUT],
+ includeUpper: false,
+ ))
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID, utxoVOUT],
+ includeLower: false,
+ upper: [inscriptionId, utxoTXID],
+ ));
+ } else {
+ return query
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID, utxoVOUT],
+ includeLower: false,
+ upper: [inscriptionId, utxoTXID],
+ ))
+ .addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID],
+ upper: [inscriptionId, utxoTXID, utxoVOUT],
+ includeUpper: false,
+ ));
+ }
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdUtxoTXIDEqualToUtxoVOUTGreaterThan(
+ String inscriptionId,
+ String utxoTXID,
+ int utxoVOUT, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID, utxoVOUT],
+ includeLower: include,
+ upper: [inscriptionId, utxoTXID],
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdUtxoTXIDEqualToUtxoVOUTLessThan(
+ String inscriptionId,
+ String utxoTXID,
+ int utxoVOUT, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID],
+ upper: [inscriptionId, utxoTXID, utxoVOUT],
+ includeUpper: include,
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdUtxoTXIDEqualToUtxoVOUTBetween(
+ String inscriptionId,
+ String utxoTXID,
+ int lowerUtxoVOUT,
+ int upperUtxoVOUT, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addWhereClause(IndexWhereClause.between(
+ indexName: r'inscriptionId_utxoTXID_utxoVOUT',
+ lower: [inscriptionId, utxoTXID, lowerUtxoVOUT],
+ includeLower: includeLower,
+ upper: [inscriptionId, utxoTXID, upperUtxoVOUT],
+ includeUpper: includeUpper,
+ ));
+ });
+ }
+}
+
+extension OrdinalQueryFilter
+ on QueryBuilder {
+ QueryBuilder contentEqualTo(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'content',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentGreaterThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'content',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentLessThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'content',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentBetween(
+ 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'content',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentStartsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.startsWith(
+ property: r'content',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentEndsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.endsWith(
+ property: r'content',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentContains(
+ String value,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.contains(
+ property: r'content',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentMatches(
+ String pattern,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.matches(
+ property: r'content',
+ wildcard: pattern,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder contentIsEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'content',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder contentIsNotEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ property: r'content',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder idEqualTo(Id value) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'id',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder idGreaterThan(
+ Id value, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'id',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder idLessThan(
+ Id value, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'id',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder idBetween(
+ Id lower,
+ Id upper, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.between(
+ property: r'id',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdEqualTo(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'inscriptionId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdGreaterThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'inscriptionId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdLessThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'inscriptionId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdBetween(
+ 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'inscriptionId',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdStartsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.startsWith(
+ property: r'inscriptionId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdEndsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.endsWith(
+ property: r'inscriptionId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdContains(
+ String value,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.contains(
+ property: r'inscriptionId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdMatches(
+ String pattern,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.matches(
+ property: r'inscriptionId',
+ wildcard: pattern,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder inscriptionIdIsEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'inscriptionId',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionIdIsNotEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ property: r'inscriptionId',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionNumberEqualTo(int value) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'inscriptionNumber',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionNumberGreaterThan(
+ int value, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'inscriptionNumber',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionNumberLessThan(
+ int value, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'inscriptionNumber',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder
+ inscriptionNumberBetween(
+ int lower,
+ int upper, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.between(
+ property: r'inscriptionNumber',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDEqualTo(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'utxoTXID',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDGreaterThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'utxoTXID',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDLessThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'utxoTXID',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDBetween(
+ 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'utxoTXID',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDStartsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.startsWith(
+ property: r'utxoTXID',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDEndsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.endsWith(
+ property: r'utxoTXID',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDContains(
+ String value,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.contains(
+ property: r'utxoTXID',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDMatches(
+ String pattern,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.matches(
+ property: r'utxoTXID',
+ wildcard: pattern,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDIsEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'utxoTXID',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder utxoTXIDIsNotEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ property: r'utxoTXID',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder utxoVOUTEqualTo(
+ int value) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'utxoVOUT',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder utxoVOUTGreaterThan(
+ int value, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'utxoVOUT',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder utxoVOUTLessThan(
+ int value, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'utxoVOUT',
+ value: value,
+ ));
+ });
+ }
+
+ QueryBuilder utxoVOUTBetween(
+ int lower,
+ int upper, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.between(
+ property: r'utxoVOUT',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdEqualTo(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'walletId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdGreaterThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'walletId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdLessThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'walletId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdBetween(
+ 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'walletId',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdStartsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.startsWith(
+ property: r'walletId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdEndsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.endsWith(
+ property: r'walletId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdContains(
+ String value,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.contains(
+ property: r'walletId',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdMatches(
+ String pattern,
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.matches(
+ property: r'walletId',
+ wildcard: pattern,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder walletIdIsEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'walletId',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder walletIdIsNotEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ property: r'walletId',
+ value: '',
+ ));
+ });
+ }
+}
+
+extension OrdinalQueryObject
+ on QueryBuilder {}
+
+extension OrdinalQueryLinks
+ on QueryBuilder {}
+
+extension OrdinalQuerySortBy on QueryBuilder {
+ QueryBuilder sortByContent() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'content', Sort.asc);
+ });
+ }
+
+ QueryBuilder sortByContentDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'content', Sort.desc);
+ });
+ }
+
+ QueryBuilder sortByInscriptionId() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionId', Sort.asc);
+ });
+ }
+
+ QueryBuilder sortByInscriptionIdDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionId', Sort.desc);
+ });
+ }
+
+ QueryBuilder sortByInscriptionNumber() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionNumber', Sort.asc);
+ });
+ }
+
+ QueryBuilder sortByInscriptionNumberDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionNumber', Sort.desc);
+ });
+ }
+
+ QueryBuilder sortByUtxoTXID() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoTXID', Sort.asc);
+ });
+ }
+
+ QueryBuilder sortByUtxoTXIDDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoTXID', Sort.desc);
+ });
+ }
+
+ QueryBuilder sortByUtxoVOUT() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoVOUT', Sort.asc);
+ });
+ }
+
+ QueryBuilder sortByUtxoVOUTDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoVOUT', Sort.desc);
+ });
+ }
+
+ QueryBuilder sortByWalletId() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'walletId', Sort.asc);
+ });
+ }
+
+ QueryBuilder sortByWalletIdDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'walletId', Sort.desc);
+ });
+ }
+}
+
+extension OrdinalQuerySortThenBy
+ on QueryBuilder {
+ QueryBuilder thenByContent() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'content', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByContentDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'content', Sort.desc);
+ });
+ }
+
+ QueryBuilder thenById() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'id', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByIdDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'id', Sort.desc);
+ });
+ }
+
+ QueryBuilder thenByInscriptionId() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionId', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByInscriptionIdDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionId', Sort.desc);
+ });
+ }
+
+ QueryBuilder thenByInscriptionNumber() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionNumber', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByInscriptionNumberDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'inscriptionNumber', Sort.desc);
+ });
+ }
+
+ QueryBuilder thenByUtxoTXID() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoTXID', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByUtxoTXIDDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoTXID', Sort.desc);
+ });
+ }
+
+ QueryBuilder thenByUtxoVOUT() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoVOUT', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByUtxoVOUTDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'utxoVOUT', Sort.desc);
+ });
+ }
+
+ QueryBuilder thenByWalletId() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'walletId', Sort.asc);
+ });
+ }
+
+ QueryBuilder thenByWalletIdDesc() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addSortBy(r'walletId', Sort.desc);
+ });
+ }
+}
+
+extension OrdinalQueryWhereDistinct
+ on QueryBuilder {
+ QueryBuilder distinctByContent(
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'content', caseSensitive: caseSensitive);
+ });
+ }
+
+ QueryBuilder distinctByInscriptionId(
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'inscriptionId',
+ caseSensitive: caseSensitive);
+ });
+ }
+
+ QueryBuilder distinctByInscriptionNumber() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'inscriptionNumber');
+ });
+ }
+
+ QueryBuilder distinctByUtxoTXID(
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'utxoTXID', caseSensitive: caseSensitive);
+ });
+ }
+
+ QueryBuilder distinctByUtxoVOUT() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'utxoVOUT');
+ });
+ }
+
+ QueryBuilder distinctByWalletId(
+ {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive);
+ });
+ }
+}
+
+extension OrdinalQueryProperty
+ on QueryBuilder {
+ QueryBuilder idProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'id');
+ });
+ }
+
+ QueryBuilder contentProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'content');
+ });
+ }
+
+ QueryBuilder inscriptionIdProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'inscriptionId');
+ });
+ }
+
+ QueryBuilder inscriptionNumberProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'inscriptionNumber');
+ });
+ }
+
+ QueryBuilder utxoTXIDProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'utxoTXID');
+ });
+ }
+
+ QueryBuilder utxoVOUTProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'utxoVOUT');
+ });
+ }
+
+ QueryBuilder walletIdProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'walletId');
+ });
+ }
+}
diff --git a/lib/pages/monkey/monkey_loaded_view.dart b/lib/pages/monkey/monkey_loaded_view.dart
new file mode 100644
index 000000000..93c28b39a
--- /dev/null
+++ b/lib/pages/monkey/monkey_loaded_view.dart
@@ -0,0 +1,275 @@
+// import 'dart:io';
+// import 'dart:typed_data';
+//
+// import 'package:flutter/material.dart';
+// import 'package:flutter_riverpod/flutter_riverpod.dart';
+// import 'package:flutter_svg/svg.dart';
+// import 'package:http/http.dart' as http;
+// import 'package:path_provider/path_provider.dart';
+// import 'package:permission_handler/permission_handler.dart';
+// import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
+// import 'package:stackwallet/providers/global/wallets_provider.dart';
+// import 'package:stackwallet/services/coins/banano/banano_wallet.dart';
+// import 'package:stackwallet/services/coins/manager.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/text_styles.dart';
+// import 'package:stackwallet/widgets/background.dart';
+// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+// import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+//
+// class MonkeyLoadedView extends ConsumerStatefulWidget {
+// const MonkeyLoadedView({
+// Key? key,
+// required this.walletId,
+// required this.managerProvider,
+// }) : super(key: key);
+//
+// static const String routeName = "/hasMonkey";
+// static const double navBarHeight = 65.0;
+//
+// final String walletId;
+// final ChangeNotifierProvider managerProvider;
+//
+// @override
+// ConsumerState createState() => _MonkeyLoadedViewState();
+// }
+//
+// class _MonkeyLoadedViewState extends ConsumerState {
+// late final String walletId;
+// late final ChangeNotifierProvider managerProvider;
+//
+// String receivingAddress = "";
+//
+// void getMonkeySVG(String address) async {
+// if (address.isEmpty) {
+// //address shouldn't be empty
+// return;
+// }
+//
+// final http.Response response = await http
+// .get(Uri.parse('https://monkey.banano.cc/api/v1/monkey/$address'));
+//
+// if (response.statusCode == 200) {
+// final decodedResponse = response.bodyBytes;
+// Directory directory = await getApplicationDocumentsDirectory();
+// late Directory sampleFolder;
+//
+// if (Platform.isAndroid) {
+// directory = Directory("/storage/emulated/0/");
+// sampleFolder = Directory('${directory!.path}Documents');
+// } else if (Platform.isIOS) {
+// sampleFolder = Directory(directory!.path);
+// } else if (Platform.isLinux) {
+// sampleFolder = Directory('${directory!.path}Documents');
+// } else if (Platform.isWindows) {
+// sampleFolder = Directory('${directory!.path}Documents');
+// } else if (Platform.isMacOS) {
+// sampleFolder = Directory('${directory!.path}Documents');
+// }
+//
+// try {
+// if (!sampleFolder.existsSync()) {
+// sampleFolder.createSync(recursive: true);
+// }
+// } catch (e, s) {
+// // todo: come back to this
+// debugPrint("$e $s");
+// }
+//
+// final docPath = sampleFolder.path;
+// final filePath = "$docPath/monkey.svg";
+//
+// File imgFile = File(filePath);
+// await imgFile.writeAsBytes(decodedResponse);
+// } else {
+// throw Exception("Failed to get MonKey");
+// }
+// }
+//
+// void getMonkeyPNG(String address) async {
+// if (address.isEmpty) {
+// //address shouldn't be empty
+// return;
+// }
+//
+// final http.Response response = await http.get(Uri.parse(
+// 'https://monkey.banano.cc/api/v1/monkey/${address}?format=png&size=512&background=false'));
+//
+// if (response.statusCode == 200) {
+// if (Platform.isAndroid) {
+// await Permission.storage.request();
+// }
+//
+// final decodedResponse = response.bodyBytes;
+// Directory directory = await getApplicationDocumentsDirectory();
+// late Directory sampleFolder;
+//
+// if (Platform.isAndroid) {
+// directory = Directory("/storage/emulated/0/");
+// sampleFolder = Directory('${directory!.path}Documents');
+// } else if (Platform.isIOS) {
+// sampleFolder = Directory(directory!.path);
+// } else if (Platform.isLinux) {
+// sampleFolder = Directory('${directory!.path}Documents');
+// } else if (Platform.isWindows) {
+// sampleFolder = Directory('${directory!.path}Documents');
+// } else if (Platform.isMacOS) {
+// sampleFolder = Directory('${directory!.path}Documents');
+// }
+//
+// try {
+// if (!sampleFolder.existsSync()) {
+// sampleFolder.createSync(recursive: true);
+// }
+// } catch (e, s) {
+// // todo: come back to this
+// debugPrint("$e $s");
+// }
+//
+// final docPath = sampleFolder.path;
+// final filePath = "$docPath/monkey.png";
+//
+// File imgFile = File(filePath);
+// await imgFile.writeAsBytes(decodedResponse);
+// } else {
+// throw Exception("Failed to get MonKey");
+// }
+// }
+//
+// @override
+// void initState() {
+// walletId = widget.walletId;
+// managerProvider = widget.managerProvider;
+//
+// WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
+// final address = await ref
+// .read(walletsChangeNotifierProvider)
+// .getManager(walletId)
+// .currentReceivingAddress;
+// setState(() {
+// receivingAddress = address;
+// });
+// });
+//
+// super.initState();
+// }
+//
+// @override
+// void dispose() {
+// super.dispose();
+// }
+//
+// @override
+// Widget build(BuildContext context) {
+// final Coin coin = ref.watch(managerProvider.select((value) => value.coin));
+// final manager = ref.watch(walletsChangeNotifierProvider
+// .select((value) => value.getManager(widget.walletId)));
+//
+// List? imageBytes;
+// imageBytes = (manager.wallet as BananoWallet).getMonkeyImageBytes();
+//
+// return Background(
+// child: Stack(
+// children: [
+// Scaffold(
+// appBar: AppBar(
+// leading: AppBarBackButton(
+// onPressed: () {
+// Navigator.of(context).popUntil(
+// ModalRoute.withName(WalletView.routeName),
+// );
+// },
+// ),
+// title: Text(
+// "MonKey",
+// style: STextStyles.navBarTitle(context),
+// ),
+// actions: [
+// AspectRatio(
+// aspectRatio: 1,
+// child: AppBarIconButton(
+// icon: SvgPicture.asset(Assets.svg.circleQuestion),
+// onPressed: () {
+// showDialog(
+// context: context,
+// useSafeArea: false,
+// barrierDismissible: true,
+// builder: (context) {
+// return Dialog(
+// child: Material(
+// borderRadius: BorderRadius.circular(
+// 20,
+// ),
+// child: Container(
+// height: 200,
+// decoration: BoxDecoration(
+// color: Theme.of(context)
+// .extension()!
+// .popupBG,
+// borderRadius: BorderRadius.circular(
+// 20,
+// ),
+// ),
+// child: Column(
+// children: [
+// Center(
+// child: Text(
+// "Help",
+// style: STextStyles.pageTitleH2(
+// context),
+// ),
+// )
+// ],
+// ),
+// ),
+// ),
+// );
+// });
+// }),
+// )
+// ],
+// ),
+// body: Column(
+// children: [
+// const Spacer(
+// flex: 1,
+// ),
+// if (imageBytes != null)
+// Container(
+// child: SvgPicture.memory(Uint8List.fromList(imageBytes!)),
+// width: 300,
+// height: 300,
+// ),
+// const Spacer(
+// flex: 1,
+// ),
+// Padding(
+// padding: const EdgeInsets.all(16.0),
+// child: Column(
+// children: [
+// SecondaryButton(
+// label: "Download as SVG",
+// onPressed: () async {
+// getMonkeySVG(receivingAddress);
+// },
+// ),
+// const SizedBox(height: 12),
+// SecondaryButton(
+// label: "Download as PNG",
+// onPressed: () {
+// getMonkeyPNG(receivingAddress);
+// },
+// ),
+// ],
+// ),
+// ),
+// ],
+// ),
+// ),
+// ],
+// ),
+// );
+// }
+// }
diff --git a/lib/pages/monkey/monkey_view.dart b/lib/pages/monkey/monkey_view.dart
new file mode 100644
index 000000000..2ad4b18eb
--- /dev/null
+++ b/lib/pages/monkey/monkey_view.dart
@@ -0,0 +1,497 @@
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:http/http.dart' as http;
+import 'package:path_provider/path_provider.dart';
+import 'package:permission_handler/permission_handler.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/services/coins/banano/banano_wallet.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/show_loading.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/background.dart';
+import 'package:stackwallet/widgets/conditional_parent.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
+import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/stack_dialog.dart';
+
+class MonkeyView extends ConsumerStatefulWidget {
+ const MonkeyView({
+ Key? key,
+ required this.walletId,
+ }) : super(key: key);
+
+ static const String routeName = "/monkey";
+ static const double navBarHeight = 65.0;
+
+ final String walletId;
+
+ @override
+ ConsumerState createState() => _MonkeyViewState();
+}
+
+class _MonkeyViewState extends ConsumerState {
+ late final String walletId;
+ List? imageBytes;
+
+ String receivingAddress = "";
+
+ Future getMonkeyImage(String address) async {
+ if (address.isEmpty) {
+ //address shouldn't be empty
+ return;
+ }
+
+ final http.Response response = await http
+ .get(Uri.parse('https://monkey.banano.cc/api/v1/monkey/$address'));
+
+ if (response.statusCode == 200) {
+ final manager =
+ ref.read(walletsChangeNotifierProvider).getManager(walletId);
+ final decodedResponse = response.bodyBytes;
+ await (manager.wallet as BananoWallet)
+ .updateMonkeyImageBytes(decodedResponse);
+ } else {
+ throw Exception("Failed to get MonKey");
+ }
+ }
+
+ // void getMonkeySVG(String address) async {
+ // if (address.isEmpty) {
+ // //address shouldn't be empty
+ // return;
+ // }
+ //
+ // final http.Response response = await http
+ // .get(Uri.parse('https://monkey.banano.cc/api/v1/monkey/$address'));
+ //
+ // if (response.statusCode == 200) {
+ // final decodedResponse = response.bodyBytes;
+ // Directory directory = await getApplicationDocumentsDirectory();
+ // late Directory sampleFolder;
+ //
+ // if (Platform.isAndroid) {
+ // directory = Directory("/storage/emulated/0/");
+ // sampleFolder = Directory('${directory!.path}Documents');
+ // } else if (Platform.isIOS) {
+ // sampleFolder = Directory(directory!.path);
+ // } else if (Platform.isLinux) {
+ // sampleFolder = Directory('${directory!.path}Documents');
+ // } else if (Platform.isWindows) {
+ // sampleFolder = Directory('${directory!.path}Documents');
+ // } else if (Platform.isMacOS) {
+ // sampleFolder = Directory('${directory!.path}Documents');
+ // }
+ //
+ // try {
+ // if (!sampleFolder.existsSync()) {
+ // sampleFolder.createSync(recursive: true);
+ // }
+ // } catch (e, s) {
+ // // todo: come back to this
+ // debugPrint("$e $s");
+ // }
+ //
+ // final docPath = sampleFolder.path;
+ // final filePath = "$docPath/monkey.svg";
+ //
+ // File imgFile = File(filePath);
+ // await imgFile.writeAsBytes(decodedResponse);
+ // } else {
+ // throw Exception("Failed to get MonKey");
+ // }
+ // }
+
+ Future getDocsDir() async {
+ try {
+ if (Platform.isAndroid) {
+ return Directory("/storage/emulated/0/Documents");
+ }
+
+ return await getApplicationDocumentsDirectory();
+ } catch (_) {
+ return null;
+ }
+ }
+
+ Future downloadMonkey(String address, bool isPNG) async {
+ if (address.isEmpty) {
+ //address shouldn't be empty
+ return;
+ }
+
+ String url = "https://monkey.banano.cc/api/v1/monkey/$address";
+
+ if (isPNG) {
+ url += '?format=png&size=512&background=false';
+ }
+
+ final http.Response response = await http.get(Uri.parse(url));
+
+ if (response.statusCode == 200) {
+ if (Platform.isAndroid) {
+ await Permission.storage.request();
+ }
+
+ final decodedResponse = response.bodyBytes;
+ final Directory? sampleFolder = await getDocsDir();
+
+ print("PATH: ${sampleFolder?.path}");
+
+ if (sampleFolder == null) {
+ print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+ return;
+ }
+
+ // try {
+ // if (!sampleFolder.existsSync()) {
+ // sampleFolder.createSync(recursive: true);
+ // }
+ // } catch (e, s) {
+ // // todo: come back to this
+ // debugPrint("$e $s");
+ // }
+
+ final docPath = sampleFolder.path;
+ String filePath = "$docPath/monkey_$address";
+
+ filePath += isPNG ? ".png" : ".svg";
+
+ // todo check if monkey.png exists
+
+ File imgFile = File(filePath);
+ await imgFile.writeAsBytes(decodedResponse);
+ } else {
+ throw Exception("Failed to get MonKey");
+ }
+ }
+
+ @override
+ void initState() {
+ walletId = widget.walletId;
+
+ WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
+ final address = await ref
+ .read(walletsChangeNotifierProvider)
+ .getManager(walletId)
+ .currentReceivingAddress;
+ setState(() {
+ receivingAddress = address;
+ });
+ });
+
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final manager = ref.watch(walletsChangeNotifierProvider
+ .select((value) => value.getManager(widget.walletId)));
+ final Coin coin = manager.coin;
+
+ final bool isDesktop = Util.isDesktop;
+
+ imageBytes ??= (manager.wallet as BananoWallet).getMonkeyImageBytes();
+
+ //edit for desktop
+ return Background(
+ child: ConditionalParent(
+ condition: isDesktop,
+ builder: (child) => DesktopScaffold(
+ appBar: DesktopAppBar(
+ background: Theme.of(context).extension()!.popupBG,
+ leading: Expanded(
+ child: Row(
+ children: [
+ const SizedBox(
+ width: 32,
+ ),
+ AppBarIconButton(
+ size: 32,
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ shadows: const [],
+ icon: SvgPicture.asset(
+ Assets.svg.arrowLeft,
+ width: 18,
+ height: 18,
+ color: Theme.of(context)
+ .extension()!
+ .topNavIconPrimary,
+ ),
+ onPressed: () {
+ if (mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ const SizedBox(
+ width: 15,
+ ),
+ SvgPicture.asset(Assets.svg.monkey),
+ const SizedBox(
+ width: 12,
+ ),
+ Text(
+ "MonKey",
+ style: STextStyles.navBarTitle(context),
+ ),
+ ],
+ ),
+ ),
+ trailing: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: MouseRegion(
+ cursor: SystemMouseCursors.click,
+ child: GestureDetector(
+ onTap: () {
+ showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return const StackDialog(
+ title: "About MonKeys",
+ message:
+ "A MonKey is a visual representation of your Banano address.",
+ );
+ });
+ },
+ child: Row(
+ children: [
+ SvgPicture.asset(
+ Assets.svg.circleQuestion,
+ color: Colors.blue[800],
+ ),
+ const SizedBox(
+ width: 6,
+ ),
+ Padding(
+ padding: const EdgeInsets.only(bottom: 8.0),
+ child: Text(
+ "What is MonKey?",
+ style: STextStyles.desktopTextSmall(context).copyWith(
+ color: Colors.blue[800],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ useSpacers: false,
+ isCompactHeight: true,
+ ),
+ body: child,
+ ),
+ child: ConditionalParent(
+ condition: !isDesktop,
+ builder: (child) => Scaffold(
+ appBar: AppBar(
+ leading: AppBarBackButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ ),
+ title: Text(
+ "MonKey",
+ style: STextStyles.navBarTitle(context),
+ ),
+ actions: [
+ AspectRatio(
+ aspectRatio: 1,
+ child: AppBarIconButton(
+ icon: SvgPicture.asset(
+ Assets.svg.circleQuestion,
+ ),
+ onPressed: () {
+ showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return const StackOkDialog(
+ title: "About MonKeys",
+ message:
+ "A MonKey is a visual representation of your Banano address.",
+ );
+ });
+ }),
+ ),
+ ],
+ ),
+ body: child,
+ ),
+ child: ConditionalParent(
+ condition: isDesktop,
+ builder: (child) => SizedBox(
+ width: 318,
+ child: child,
+ ),
+ child: ConditionalParent(
+ condition: imageBytes != null,
+ builder: (_) => Column(
+ children: [
+ isDesktop
+ ? const SizedBox(
+ height: 50,
+ )
+ : const Spacer(
+ flex: 1,
+ ),
+ if (imageBytes != null)
+ SizedBox(
+ width: 300,
+ height: 300,
+ child: SvgPicture.memory(Uint8List.fromList(imageBytes!)),
+ ),
+ isDesktop
+ ? const SizedBox(
+ height: 50,
+ )
+ : const Spacer(
+ flex: 1,
+ ),
+ Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ children: [
+ SecondaryButton(
+ label: "Save as SVG",
+ onPressed: () async {
+ await showLoading(
+ whileFuture:
+ downloadMonkey(receivingAddress, false),
+ context: context,
+ isDesktop: Util.isDesktop,
+ message: "Saving MonKey svg",
+ );
+ },
+ ),
+ const SizedBox(height: 12),
+ SecondaryButton(
+ label: "Download as PNG",
+ onPressed: () async {
+ await showLoading(
+ whileFuture:
+ downloadMonkey(receivingAddress, true),
+ context: context,
+ isDesktop: Util.isDesktop,
+ message: "Downloading MonKey png",
+ );
+ },
+ ),
+ ],
+ ),
+ ),
+ // child,
+ ],
+ ),
+ child: Column(
+ children: [
+ isDesktop
+ ? const SizedBox(
+ height: 100,
+ )
+ : const Spacer(
+ flex: 4,
+ ),
+ Center(
+ child: Column(
+ children: [
+ Opacity(
+ opacity: 0.2,
+ child: SvgPicture.file(
+ File(
+ ref.watch(coinIconProvider(coin)),
+ ),
+ width: 200,
+ height: 200,
+ ),
+ ),
+ const SizedBox(
+ height: 70,
+ ),
+ Text(
+ "You do not have a MonKey yet. \nFetch yours now!",
+ style: STextStyles.smallMed14(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textDark3,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ ],
+ ),
+ ),
+ isDesktop
+ ? const SizedBox(
+ height: 50,
+ )
+ : const Spacer(
+ flex: 6,
+ ),
+ Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: PrimaryButton(
+ label: "Fetch MonKey",
+ onPressed: () async {
+ final future = Future.wait([
+ getMonkeyImage(receivingAddress),
+ Future.delayed(const Duration(seconds: 2)),
+ ]);
+
+ await showLoading(
+ whileFuture: future,
+ context: context,
+ isDesktop: Util.isDesktop,
+ message: "Fetching MonKey",
+ subMessage: "We are fetching your MonKey",
+ );
+
+ imageBytes = (manager.wallet as BananoWallet)
+ .getMonkeyImageBytes();
+
+ if (imageBytes != null) {
+ setState(() {});
+ }
+
+ // if (isDesktop) {
+ // Navigator.of(context).popUntil(
+ // ModalRoute.withName(
+ // DesktopWalletView.routeName),
+ // );
+ // } else {
+ // Navigator.of(context).popUntil(
+ // ModalRoute.withName(WalletView.routeName),
+ // );
+ // }
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/monkey/sub_widgets/fetch_monkey_dialog.dart b/lib/pages/monkey/sub_widgets/fetch_monkey_dialog.dart
new file mode 100644
index 000000000..94034fb78
--- /dev/null
+++ b/lib/pages/monkey/sub_widgets/fetch_monkey_dialog.dart
@@ -0,0 +1,135 @@
+/*
+ * This file is part of Stack Wallet.
+ *
+ * Copyright (c) 2023 Cypher Stack
+ * All Rights Reserved.
+ * The code is distributed under GPLv3 license, see LICENSE file for details.
+ * Generated by Cypher Stack on 2023-05-26
+ *
+ */
+
+import 'package:flutter/material.dart';
+import 'package:stackwallet/themes/stack_colors.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/animated_widgets/rotating_arrows.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/stack_dialog.dart';
+
+class FetchMonkeyDialog extends StatefulWidget {
+ const FetchMonkeyDialog({
+ Key? key,
+ required this.onCancel,
+ }) : super(key: key);
+
+ final Future Function() onCancel;
+
+ @override
+ State createState() => _FetchMonkeyDialogState();
+}
+
+class _FetchMonkeyDialogState extends State {
+ late final Future Function() onCancel;
+ @override
+ void initState() {
+ onCancel = widget.onCancel;
+
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ if (Util.isDesktop) {
+ return DesktopDialog(
+ child: Column(
+ children: [
+ DesktopDialogCloseButton(
+ onPressedOverride: () async {
+ await onCancel.call();
+ if (mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ const Spacer(
+ flex: 1,
+ ),
+ const RotatingArrows(
+ width: 40,
+ height: 40,
+ ),
+ const Spacer(
+ flex: 2,
+ ),
+ Text(
+ "Fetching MonKey",
+ style: STextStyles.desktopH2(context),
+ textAlign: TextAlign.center,
+ ),
+ const SizedBox(
+ height: 16,
+ ),
+ Text(
+ "We are fetching your MonKey",
+ style: STextStyles.desktopTextMedium(context).copyWith(
+ color: Theme.of(context).extension()!.textDark3,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ const Spacer(
+ flex: 2,
+ ),
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 32,
+ right: 32,
+ bottom: 32,
+ ),
+ child: SecondaryButton(
+ label: "Cancel",
+ width: 272.5,
+ onPressed: () async {
+ await onCancel.call();
+ if (mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ ),
+ ],
+ ),
+ );
+ } else {
+ return WillPopScope(
+ onWillPop: () async {
+ return false;
+ },
+ child: StackDialog(
+ title: "Fetching MonKey",
+ message: "We are fetching your MonKey",
+ icon: const RotatingArrows(
+ width: 24,
+ height: 24,
+ ),
+ rightButton: TextButton(
+ style: Theme.of(context)
+ .extension()!
+ .getSecondaryEnabledButtonStyle(context),
+ child: Text(
+ "Cancel",
+ style: STextStyles.itemSubtitle12(context),
+ ),
+ onPressed: () async {
+ await onCancel.call();
+ if (mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ ),
+ );
+ }
+ }
+}
diff --git a/lib/pages/ordinals/ordinal_details_view.dart b/lib/pages/ordinals/ordinal_details_view.dart
new file mode 100644
index 000000000..ced80c42c
--- /dev/null
+++ b/lib/pages/ordinals/ordinal_details_view.dart
@@ -0,0 +1,267 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/models/isar/ordinal.dart';
+import 'package:stackwallet/notifications/show_flush_bar.dart';
+import 'package:stackwallet/pages/ordinals/widgets/dialogs.dart';
+import 'package:stackwallet/themes/stack_colors.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/background.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_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 OrdinalDetailsView extends StatefulWidget {
+ const OrdinalDetailsView({
+ Key? key,
+ required this.walletId,
+ required this.ordinal,
+ }) : super(key: key);
+
+ final String walletId;
+ final Ordinal ordinal;
+
+ static const routeName = "/ordinalDetailsView";
+
+ @override
+ State createState() => _OrdinalDetailsViewState();
+}
+
+class _OrdinalDetailsViewState extends State {
+ static const _spacing = 12.0;
+
+ @override
+ Widget build(BuildContext context) {
+ return Background(
+ child: SafeArea(
+ child: Scaffold(
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ appBar: AppBar(
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ leading: const AppBarBackButton(),
+ title: Text(
+ "Ordinal details",
+ style: STextStyles.navBarTitle(context),
+ ),
+ ),
+ body: SingleChildScrollView(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 12,
+ horizontal: 39,
+ ),
+ child: _OrdinalImageGroup(
+ ordinal: widget.ordinal,
+ walletId: widget.walletId,
+ ),
+ ),
+ _DetailsItemWCopy(
+ title: "Inscription number",
+ data: widget.ordinal.inscriptionNumber.toString(),
+ ),
+ const SizedBox(
+ height: _spacing,
+ ),
+ _DetailsItemWCopy(
+ title: "ID",
+ data: widget.ordinal.inscriptionId,
+ ),
+ const SizedBox(
+ height: _spacing,
+ ),
+ // todo: add utxo status
+ const SizedBox(
+ height: _spacing,
+ ),
+ const _DetailsItemWCopy(
+ title: "Amount",
+ data: "TODO", // TODO infer from utxo utxoTXID:utxoVOUT
+ ),
+ const SizedBox(
+ height: _spacing,
+ ),
+ const _DetailsItemWCopy(
+ title: "Owner address",
+ data: "TODO", // infer from address associated w utxoTXID
+ ),
+ const SizedBox(
+ height: _spacing,
+ ),
+ _DetailsItemWCopy(
+ title: "Transaction ID",
+ data: widget.ordinal.utxoTXID,
+ ),
+ const SizedBox(
+ height: _spacing,
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
+
+class _DetailsItemWCopy extends StatelessWidget {
+ const _DetailsItemWCopy({
+ Key? key,
+ required this.title,
+ required this.data,
+ }) : super(key: key);
+
+ final String title;
+ final String data;
+
+ @override
+ Widget build(BuildContext context) {
+ return RoundedWhiteContainer(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ title,
+ style: STextStyles.itemSubtitle(context),
+ ),
+ GestureDetector(
+ onTap: () async {
+ await Clipboard.setData(ClipboardData(text: data));
+ if (context.mounted) {
+ unawaited(
+ showFloatingFlushBar(
+ type: FlushBarType.info,
+ message: "Copied to clipboard",
+ context: context,
+ ),
+ );
+ }
+ },
+ child: SvgPicture.asset(
+ Assets.svg.copy,
+ color:
+ Theme.of(context).extension()!.infoItemIcons,
+ width: 12,
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(
+ height: 4,
+ ),
+ SelectableText(
+ data,
+ style: STextStyles.itemSubtitle12(context),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _OrdinalImageGroup extends StatelessWidget {
+ const _OrdinalImageGroup({
+ Key? key,
+ required this.walletId,
+ required this.ordinal,
+ }) : super(key: key);
+
+ final String walletId;
+ final Ordinal ordinal;
+
+ static const _spacing = 12.0;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ // Text(
+ // "${ordinal.inscriptionId}", // Use any other property you want
+ // style: STextStyles.w600_16(context),
+ // ),
+ // const SizedBox(
+ // height: _spacing,
+ // ),
+ AspectRatio(
+ aspectRatio: 1,
+ child: Container(
+ color: Colors.transparent,
+ child: Image.network(
+ ordinal.content, // Use the preview URL as the image source
+ fit: BoxFit.cover,
+ filterQuality:
+ FilterQuality.none, // Set the filter mode to nearest
+ ),
+ ),
+ ),
+ const SizedBox(
+ height: _spacing,
+ ),
+ Row(
+ children: [
+ Expanded(
+ child: SecondaryButton(
+ label: "Download",
+ icon: SvgPicture.asset(
+ Assets.svg.arrowDown,
+ width: 10,
+ height: 12,
+ color: Theme.of(context)
+ .extension()!
+ .buttonTextSecondary,
+ ),
+ buttonHeight: ButtonHeight.l,
+ iconSpacing: 4,
+ onPressed: () {
+ // TODO: save and download image to device
+ },
+ ),
+ ),
+ // const SizedBox(
+ // width: _spacing,
+ // ),
+ // Expanded(
+ // child: PrimaryButton(
+ // label: "Send",
+ // icon: SvgPicture.asset(
+ // Assets.svg.send,
+ // width: 10,
+ // height: 10,
+ // color: Theme.of(context)
+ // .extension()!
+ // .buttonTextPrimary,
+ // ),
+ // buttonHeight: ButtonHeight.l,
+ // iconSpacing: 4,
+ // onPressed: () async {
+ // final response = await showDialog(
+ // context: context,
+ // builder: (_) => const SendOrdinalUnfreezeDialog(),
+ // );
+ // if (response == "unfreeze") {
+ // // TODO: unfreeze and go to send ord screen
+ // }
+ // },
+ // ),
+ // ),
+ ],
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/pages/ordinals/ordinals_filter_view.dart b/lib/pages/ordinals/ordinals_filter_view.dart
new file mode 100644
index 000000000..631a9833a
--- /dev/null
+++ b/lib/pages/ordinals/ordinals_filter_view.dart
@@ -0,0 +1,889 @@
+/*
+ * This file is part of Stack Wallet.
+ *
+ * Copyright (c) 2023 Cypher Stack
+ * All Rights Reserved.
+ * The code is distributed under GPLv3 license, see LICENSE file for details.
+ * Generated by Cypher Stack on 2023-05-26
+ *
+ */
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart';
+import 'package:flutter_svg/svg.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/format.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/background.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.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/icon_widgets/x_icon.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+import 'package:stackwallet/widgets/textfield_icon_button.dart';
+
+class OrdinalFilter {
+ // final bool isMoonbird;
+ // final bool isPunk;
+ final DateTime? from;
+ final DateTime? to;
+ final String? inscription;
+ final String keyword;
+
+ OrdinalFilter({
+ // required this.isMoonbird,
+ // required this.isPunk,
+ required this.from,
+ required this.to,
+ required this.inscription,
+ required this.keyword,
+ });
+
+ OrdinalFilter copyWith({
+ // bool? isMoonbird,
+ // bool? isPunk,
+ DateTime? from,
+ DateTime? to,
+ String? inscription,
+ String? keyword,
+ }) {
+ return OrdinalFilter(
+ // isMoonbird: isMoonbird ?? this.isMoonbird,
+ // isPunk: isPunk ?? this.isPunk,
+ from: from ?? this.from,
+ to: to ?? this.to,
+ inscription: inscription ?? this.inscription,
+ keyword: keyword ?? this.keyword,
+ );
+ }
+}
+
+final ordinalFilterProvider = StateProvider((_) => null);
+
+class OrdinalsFilterView extends ConsumerStatefulWidget {
+ const OrdinalsFilterView({
+ Key? key,
+ }) : super(key: key);
+
+ static const String routeName = "/ordinalsFilterView";
+
+ @override
+ ConsumerState createState() => _OrdinalsFilterViewState();
+}
+
+class _OrdinalsFilterViewState extends ConsumerState {
+ final _inscriptionTextEditingController = TextEditingController();
+ final _keywordTextEditingController = TextEditingController();
+
+ // bool _isPunk = false;
+ // bool _isMoonbird = false;
+
+ String _fromDateString = "";
+ String _toDateString = "";
+
+ final keywordTextFieldFocusNode = FocusNode();
+ final inscriptionTextFieldFocusNode = FocusNode();
+
+ late Color baseColor;
+
+ @override
+ initState() {
+ baseColor = ref.read(themeProvider.state).state.textSubtitle2;
+ final filterState = ref.read(ordinalFilterProvider.state).state;
+ if (filterState != null) {
+ // _isMoonbird = filterState.isMoonbird;
+ // _isPunk = filterState.isPunk;
+ _selectedToDate = filterState.to;
+ _selectedFromDate = filterState.from;
+ _keywordTextEditingController.text = filterState.keyword;
+ _inscriptionTextEditingController.text = filterState.inscription ?? "";
+ }
+
+ super.initState();
+ }
+
+ @override
+ dispose() {
+ _inscriptionTextEditingController.dispose();
+ _keywordTextEditingController.dispose();
+ keywordTextFieldFocusNode.dispose();
+ inscriptionTextFieldFocusNode.dispose();
+
+ super.dispose();
+ }
+
+ // The following two getters are not required if the
+ // date fields are to remain unclearable.
+ Widget get _dateFromText {
+ final isDateSelected = _fromDateString.isEmpty;
+ return Text(
+ isDateSelected ? "From..." : _fromDateString,
+ style: STextStyles.fieldLabel(context).copyWith(
+ color: isDateSelected
+ ? Theme.of(context).extension()!.textSubtitle2
+ : Theme.of(context).extension()!.accentColorDark),
+ );
+ }
+
+ Widget get _dateToText {
+ final isDateSelected = _toDateString.isEmpty;
+ return Text(
+ isDateSelected ? "To..." : _toDateString,
+ style: STextStyles.fieldLabel(context).copyWith(
+ color: isDateSelected
+ ? Theme.of(context).extension()!.textSubtitle2
+ : Theme.of(context).extension()!.accentColorDark),
+ );
+ }
+
+ DateTime? _selectedFromDate = DateTime(2007);
+ DateTime? _selectedToDate = DateTime.now();
+
+ MaterialRoundedDatePickerStyle _buildDatePickerStyle() {
+ return MaterialRoundedDatePickerStyle(
+ backgroundPicker: Theme.of(context).extension()!.popupBG,
+ // backgroundHeader: Theme.of(context).extension()!.textSubtitle2,
+ paddingMonthHeader: const EdgeInsets.only(top: 11),
+ colorArrowNext: Theme.of(context).extension()!.textSubtitle1,
+ colorArrowPrevious:
+ Theme.of(context).extension()!.textSubtitle1,
+ textStyleButtonNegative: STextStyles.datePicker600(context).copyWith(
+ color: baseColor,
+ ),
+ textStyleButtonPositive: STextStyles.datePicker600(context).copyWith(
+ color: baseColor,
+ ),
+ textStyleCurrentDayOnCalendar: STextStyles.datePicker400(context),
+ textStyleDayHeader: STextStyles.datePicker600(context),
+ textStyleDayOnCalendar: STextStyles.datePicker400(context).copyWith(
+ color: baseColor,
+ ),
+ textStyleDayOnCalendarDisabled:
+ STextStyles.datePicker400(context).copyWith(
+ color: Theme.of(context).extension()!.textSubtitle3,
+ ),
+ textStyleDayOnCalendarSelected:
+ STextStyles.datePicker400(context).copyWith(
+ color: Theme.of(context).extension()!.textWhite,
+ ),
+ textStyleMonthYearHeader: STextStyles.datePicker600(context).copyWith(
+ color: Theme.of(context).extension()!.textSubtitle1,
+ ),
+ textStyleYearButton: STextStyles.datePicker600(context).copyWith(
+ color: Theme.of(context).extension()!.textWhite,
+ ),
+ // textStyleButtonAction: GoogleFonts.inter(),
+ );
+ }
+
+ MaterialRoundedYearPickerStyle _buildYearPickerStyle() {
+ return MaterialRoundedYearPickerStyle(
+ backgroundPicker: Theme.of(context).extension()!.popupBG,
+ textStyleYear: STextStyles.datePicker600(context).copyWith(
+ color: Theme.of(context).extension()!.textSubtitle2,
+ fontSize: 16,
+ ),
+ textStyleYearSelected: STextStyles.datePicker600(context).copyWith(
+ fontSize: 18,
+ ),
+ );
+ }
+
+ Widget _buildDateRangePicker() {
+ const middleSeparatorPadding = 2.0;
+ const middleSeparatorWidth = 12.0;
+ final isDesktop = Util.isDesktop;
+
+ final width = isDesktop
+ ? null
+ : (MediaQuery.of(context).size.width -
+ (middleSeparatorWidth +
+ (2 * middleSeparatorPadding) +
+ (2 * Constants.size.standardPadding))) /
+ 2;
+
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: GestureDetector(
+ key: const Key("OrdinalsViewFromDatePickerKey"),
+ onTap: () async {
+ final color =
+ Theme.of(context).extension()!.accentColorDark;
+ final height = MediaQuery.of(context).size.height;
+ // check and hide keyboard
+ if (FocusScope.of(context).hasFocus) {
+ FocusScope.of(context).unfocus();
+ await Future.delayed(const Duration(milliseconds: 125));
+ }
+
+ if (mounted) {
+ final date = await showRoundedDatePicker(
+ // This doesn't change statusbar color...
+ // background: CFColors.starryNight.withOpacity(0.8),
+ context: context,
+ initialDate: DateTime.now(),
+ height: height * 0.5,
+ theme: ThemeData(
+ primarySwatch: Util.createMaterialColor(
+ color,
+ ),
+ ),
+ //TODO pick a better initial date
+ // 2007 chosen as that is just before bitcoin launched
+ firstDate: DateTime(2007),
+ lastDate: DateTime.now(),
+ borderRadius: Constants.size.circularBorderRadius * 2,
+
+ textPositiveButton: "SELECT",
+
+ styleDatePicker: _buildDatePickerStyle(),
+ styleYearPicker: _buildYearPickerStyle(),
+ );
+ if (date != null) {
+ _selectedFromDate = date;
+
+ // flag to adjust date so from date is always before to date
+ final flag = _selectedToDate != null &&
+ !_selectedFromDate!.isBefore(_selectedToDate!);
+ if (flag) {
+ _selectedToDate = DateTime.fromMillisecondsSinceEpoch(
+ _selectedFromDate!.millisecondsSinceEpoch);
+ }
+
+ setState(() {
+ if (flag) {
+ _toDateString = _selectedToDate == null
+ ? ""
+ : Format.formatDate(_selectedToDate!);
+ }
+ _fromDateString = _selectedFromDate == null
+ ? ""
+ : Format.formatDate(_selectedFromDate!);
+ });
+ }
+ }
+ },
+ child: Container(
+ width: width,
+ decoration: BoxDecoration(
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ borderRadius:
+ BorderRadius.circular(Constants.size.circularBorderRadius),
+ border: Border.all(
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ width: 1,
+ ),
+ ),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: 12,
+ vertical: isDesktop ? 17 : 12,
+ ),
+ child: Row(
+ children: [
+ SvgPicture.asset(
+ Assets.svg.calendar,
+ height: 20,
+ width: 20,
+ color: Theme.of(context)
+ .extension()!
+ .textSubtitle2,
+ ),
+ const SizedBox(
+ width: 10,
+ ),
+ Align(
+ alignment: Alignment.centerLeft,
+ child: FittedBox(
+ child: _dateFromText,
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ const EdgeInsets.symmetric(horizontal: middleSeparatorPadding),
+ child: Container(
+ width: middleSeparatorWidth,
+ // height: 1,
+ // color: CFColors.smoke,
+ ),
+ ),
+ Expanded(
+ child: GestureDetector(
+ key: const Key("OrdinalsViewToDatePickerKey"),
+ onTap: () async {
+ final color =
+ Theme.of(context).extension()!.accentColorDark;
+ final height = MediaQuery.of(context).size.height;
+ // check and hide keyboard
+ if (FocusScope.of(context).hasFocus) {
+ FocusScope.of(context).unfocus();
+ await Future.delayed(const Duration(milliseconds: 125));
+ }
+
+ if (mounted) {
+ final date = await showRoundedDatePicker(
+ // This doesn't change statusbar color...
+ // background: CFColors.starryNight.withOpacity(0.8),
+ context: context,
+ height: height * 0.5,
+ theme: ThemeData(
+ primarySwatch: Util.createMaterialColor(
+ color,
+ ),
+ ),
+ //TODO pick a better initial date
+ // 2007 chosen as that is just before bitcoin launched
+ initialDate: DateTime.now(),
+ firstDate: DateTime(2007),
+ lastDate: DateTime.now(),
+ borderRadius: Constants.size.circularBorderRadius * 2,
+
+ textPositiveButton: "SELECT",
+
+ styleDatePicker: _buildDatePickerStyle(),
+ styleYearPicker: _buildYearPickerStyle(),
+ );
+ if (date != null) {
+ _selectedToDate = date;
+
+ // flag to adjust date so from date is always before to date
+ final flag = _selectedFromDate != null &&
+ !_selectedToDate!.isAfter(_selectedFromDate!);
+ if (flag) {
+ _selectedFromDate = DateTime.fromMillisecondsSinceEpoch(
+ _selectedToDate!.millisecondsSinceEpoch);
+ }
+
+ setState(() {
+ if (flag) {
+ _fromDateString = _selectedFromDate == null
+ ? ""
+ : Format.formatDate(_selectedFromDate!);
+ }
+ _toDateString = _selectedToDate == null
+ ? ""
+ : Format.formatDate(_selectedToDate!);
+ });
+ }
+ }
+ },
+ child: Container(
+ width: width,
+ decoration: BoxDecoration(
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ borderRadius:
+ BorderRadius.circular(Constants.size.circularBorderRadius),
+ border: Border.all(
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ width: 1,
+ ),
+ ),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: 12,
+ vertical: isDesktop ? 17 : 12,
+ ),
+ child: Row(
+ children: [
+ SvgPicture.asset(
+ Assets.svg.calendar,
+ height: 20,
+ width: 20,
+ color: Theme.of(context)
+ .extension()!
+ .textSubtitle2,
+ ),
+ const SizedBox(
+ width: 10,
+ ),
+ Align(
+ alignment: Alignment.centerLeft,
+ child: FittedBox(
+ child: _dateToText,
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ if (isDesktop)
+ const SizedBox(
+ width: 24,
+ ),
+ ],
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ if (Util.isDesktop) {
+ return DesktopDialog(
+ maxWidth: 576,
+ maxHeight: double.infinity,
+ child: Padding(
+ padding: const EdgeInsets.only(
+ left: 32,
+ bottom: 32,
+ ),
+ child: _buildContent(context),
+ ),
+ );
+ } else {
+ return Background(
+ child: Scaffold(
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ appBar: AppBar(
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ leading: AppBarBackButton(
+ onPressed: () async {
+ if (FocusScope.of(context).hasFocus) {
+ FocusScope.of(context).unfocus();
+ await Future.delayed(const Duration(milliseconds: 75));
+ }
+ if (mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ title: Text(
+ "Ordinals filter",
+ style: STextStyles.navBarTitle(context),
+ ),
+ ),
+ body: Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: Constants.size.standardPadding,
+ ),
+ child: LayoutBuilder(
+ builder: (context, constraints) {
+ return SingleChildScrollView(
+ child: ConstrainedBox(
+ constraints:
+ BoxConstraints(minHeight: constraints.maxHeight),
+ child: IntrinsicHeight(
+ child: _buildContent(context),
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+ }
+
+ Widget _buildContent(BuildContext context) {
+ final isDesktop = Util.isDesktop;
+
+ return Column(
+ children: [
+ if (isDesktop)
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ "Ordinals filter",
+ style: STextStyles.desktopH3(context),
+ textAlign: TextAlign.center,
+ ),
+ const DesktopDialogCloseButton(),
+ ],
+ ),
+ SizedBox(
+ height: isDesktop ? 14 : 10,
+ ),
+ // if (!isDesktop)
+ // Align(
+ // alignment: Alignment.centerLeft,
+ // child: FittedBox(
+ // child: Text(
+ // "Collection",
+ // style: STextStyles.smallMed12(context),
+ // ),
+ // ),
+ // ),
+ // if (!isDesktop)
+ // const SizedBox(
+ // height: 12,
+ // ),
+ // RoundedWhiteContainer(
+ // padding: EdgeInsets.all(isDesktop ? 0 : 12),
+ // child: Column(
+ // crossAxisAlignment: CrossAxisAlignment.start,
+ // children: [
+ // Row(
+ // children: [
+ // GestureDetector(
+ // onTap: () {
+ // setState(() {
+ // _isPunk = !_isPunk;
+ // });
+ // },
+ // child: Container(
+ // color: Colors.transparent,
+ // child: Row(
+ // children: [
+ // SizedBox(
+ // height: 20,
+ // width: 20,
+ // child: Checkbox(
+ // key: const Key("OrdinalsPunkCheckboxKey"),
+ // materialTapTargetSize:
+ // MaterialTapTargetSize.shrinkWrap,
+ // value: _isPunk,
+ // onChanged: (newValue) {
+ // setState(() {
+ // _isPunk = newValue!;
+ // });
+ // },
+ // ),
+ // ),
+ // const SizedBox(
+ // width: 14,
+ // ),
+ // Align(
+ // alignment: Alignment.centerLeft,
+ // child: FittedBox(
+ // child: Column(
+ // children: [
+ // Text(
+ // "Punks",
+ // style: isDesktop
+ // ? STextStyles.desktopTextSmall(context)
+ // : STextStyles.itemSubtitle12(context),
+ // ),
+ // if (isDesktop)
+ // const SizedBox(
+ // height: 4,
+ // ),
+ // ],
+ // ),
+ // ),
+ // )
+ // ],
+ // ),
+ // ),
+ // ),
+ // ],
+ // ),
+ // SizedBox(
+ // height: isDesktop ? 4 : 10,
+ // ),
+ // Row(
+ // children: [
+ // GestureDetector(
+ // onTap: () {
+ // setState(() {
+ // _isMoonbird = !_isMoonbird;
+ // });
+ // },
+ // child: Container(
+ // color: Colors.transparent,
+ // child: Row(
+ // children: [
+ // SizedBox(
+ // height: 20,
+ // width: 20,
+ // child: Checkbox(
+ // key: const Key(
+ // "OrdinalsFilterMoonbirdCheckboxKey",
+ // ),
+ // materialTapTargetSize:
+ // MaterialTapTargetSize.shrinkWrap,
+ // value: _isMoonbird,
+ // onChanged: (newValue) {
+ // setState(() {
+ // _isMoonbird = newValue!;
+ // });
+ // },
+ // ),
+ // ),
+ // const SizedBox(
+ // width: 14,
+ // ),
+ // Align(
+ // alignment: Alignment.centerLeft,
+ // child: FittedBox(
+ // child: Column(
+ // children: [
+ // Text(
+ // "Moonbirds",
+ // style: isDesktop
+ // ? STextStyles.desktopTextSmall(context)
+ // : STextStyles.itemSubtitle12(context),
+ // ),
+ // if (isDesktop)
+ // const SizedBox(
+ // height: 4,
+ // ),
+ // ],
+ // ),
+ // ),
+ // )
+ // ],
+ // ),
+ // ),
+ // ),
+ // ],
+ // ),
+ // ],
+ // ),
+ // ),
+ // SizedBox(
+ // height: isDesktop ? 32 : 24,
+ // ),
+ Align(
+ alignment: Alignment.centerLeft,
+ child: FittedBox(
+ child: Text(
+ "Date",
+ style: isDesktop
+ ? STextStyles.labelExtraExtraSmall(context)
+ : STextStyles.smallMed12(context),
+ ),
+ ),
+ ),
+ SizedBox(
+ height: isDesktop ? 10 : 8,
+ ),
+ _buildDateRangePicker(),
+ SizedBox(
+ height: isDesktop ? 32 : 24,
+ ),
+ Align(
+ alignment: Alignment.centerLeft,
+ child: FittedBox(
+ child: Text(
+ "Inscription",
+ style: isDesktop
+ ? STextStyles.labelExtraExtraSmall(context)
+ : STextStyles.smallMed12(context),
+ ),
+ ),
+ ),
+ SizedBox(
+ height: isDesktop ? 10 : 8,
+ ),
+ Padding(
+ padding: EdgeInsets.only(right: isDesktop ? 32 : 0),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ child: TextField(
+ autocorrect: Util.isDesktop ? false : true,
+ enableSuggestions: Util.isDesktop ? false : true,
+ key: const Key("OrdinalsInscriptionFieldKey"),
+ controller: _inscriptionTextEditingController,
+ focusNode: inscriptionTextFieldFocusNode,
+ onChanged: (_) => setState(() {}),
+ style: isDesktop
+ ? STextStyles.desktopTextExtraSmall(context).copyWith(
+ color:
+ Theme.of(context).extension()!.textDark,
+ height: 1.8,
+ )
+ : STextStyles.field(context),
+ decoration: standardInputDecoration(
+ "Enter inscription number...",
+ keywordTextFieldFocusNode,
+ context,
+ desktopMed: isDesktop,
+ ).copyWith(
+ contentPadding: isDesktop
+ ? const EdgeInsets.symmetric(
+ vertical: 10,
+ horizontal: 16,
+ )
+ : null,
+ suffixIcon: _inscriptionTextEditingController.text.isNotEmpty
+ ? Padding(
+ padding: const EdgeInsets.only(right: 0),
+ child: UnconstrainedBox(
+ child: Row(
+ children: [
+ TextFieldIconButton(
+ child: const XIcon(),
+ onTap: () async {
+ setState(() {
+ _inscriptionTextEditingController.text = "";
+ });
+ },
+ ),
+ ],
+ ),
+ ),
+ )
+ : null,
+ ),
+ ),
+ ),
+ ),
+ SizedBox(
+ height: isDesktop ? 32 : 24,
+ ),
+ Align(
+ alignment: Alignment.centerLeft,
+ child: FittedBox(
+ child: Text(
+ "Keyword",
+ style: isDesktop
+ ? STextStyles.labelExtraExtraSmall(context)
+ : STextStyles.smallMed12(context),
+ ),
+ ),
+ ),
+ SizedBox(
+ height: isDesktop ? 10 : 8,
+ ),
+ Padding(
+ padding: EdgeInsets.only(right: isDesktop ? 32 : 0),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ child: TextField(
+ autocorrect: Util.isDesktop ? false : true,
+ enableSuggestions: Util.isDesktop ? false : true,
+ key: const Key("OrdinalsViewKeywordFieldKey"),
+ controller: _keywordTextEditingController,
+ focusNode: keywordTextFieldFocusNode,
+ style: isDesktop
+ ? STextStyles.desktopTextExtraSmall(context).copyWith(
+ color:
+ Theme.of(context).extension()!.textDark,
+ height: 1.8,
+ )
+ : STextStyles.field(context),
+ onChanged: (_) => setState(() {}),
+ decoration: standardInputDecoration(
+ "Type keyword...",
+ keywordTextFieldFocusNode,
+ context,
+ desktopMed: isDesktop,
+ ).copyWith(
+ contentPadding: isDesktop
+ ? const EdgeInsets.symmetric(
+ vertical: 10,
+ horizontal: 16,
+ )
+ : null,
+ suffixIcon: _keywordTextEditingController.text.isNotEmpty
+ ? Padding(
+ padding: const EdgeInsets.only(right: 0),
+ child: UnconstrainedBox(
+ child: Row(
+ children: [
+ TextFieldIconButton(
+ child: const XIcon(),
+ onTap: () async {
+ setState(() {
+ _keywordTextEditingController.text = "";
+ });
+ },
+ ),
+ ],
+ ),
+ ),
+ )
+ : null,
+ ),
+ ),
+ ),
+ ),
+ if (!isDesktop) const Spacer(),
+ SizedBox(
+ height: isDesktop ? 32 : 20,
+ ),
+ Row(
+ children: [
+ Expanded(
+ child: SecondaryButton(
+ label: "Cancel",
+ buttonHeight: isDesktop ? ButtonHeight.l : null,
+ onPressed: () async {
+ if (!isDesktop) {
+ if (FocusScope.of(context).hasFocus) {
+ FocusScope.of(context).unfocus();
+ await Future.delayed(
+ const Duration(
+ milliseconds: 75,
+ ),
+ );
+ }
+ }
+ if (mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ ),
+ const SizedBox(
+ width: 16,
+ ),
+ Expanded(
+ child: PrimaryButton(
+ buttonHeight: isDesktop ? ButtonHeight.l : null,
+ onPressed: () async {
+ await _onApplyPressed();
+ },
+ label: "Save",
+ ),
+ ),
+ if (isDesktop)
+ const SizedBox(
+ width: 32,
+ ),
+ ],
+ ),
+ if (!isDesktop)
+ const SizedBox(
+ height: 20,
+ ),
+ ],
+ );
+ }
+
+ Future _onApplyPressed() async {
+ final filter = OrdinalFilter(
+ // isPunk: _isPunk,
+ // isMoonbird: _isMoonbird,
+ from: _selectedFromDate,
+ to: _selectedToDate,
+ inscription: _inscriptionTextEditingController.text,
+ keyword: _keywordTextEditingController.text,
+ );
+
+ ref.read(ordinalFilterProvider.state).state = filter;
+
+ Navigator.of(context).pop();
+ }
+}
diff --git a/lib/pages/ordinals/ordinals_view.dart b/lib/pages/ordinals/ordinals_view.dart
new file mode 100644
index 000000000..45b30655a
--- /dev/null
+++ b/lib/pages/ordinals/ordinals_view.dart
@@ -0,0 +1,202 @@
+/*
+ * This file is part of Stack Wallet.
+ *
+ * Copyright (c) 2023 Cypher Stack
+ * All Rights Reserved.
+ * The code is distributed under GPLv3 license, see LICENSE file for details.
+ * Generated by Cypher Stack on 2023-05-26
+ *
+ */
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/pages/ordinals/widgets/ordinals_list.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/services/mixins/ordinals_interface.dart';
+import 'package:stackwallet/themes/stack_colors.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/show_loading.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/background.dart';
+import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
+
+class OrdinalsView extends ConsumerStatefulWidget {
+ const OrdinalsView({
+ super.key,
+ required this.walletId,
+ });
+
+ static const routeName = "/ordinalsView";
+
+ final String walletId;
+
+ @override
+ ConsumerState createState() => _OrdinalsViewState();
+}
+
+class _OrdinalsViewState extends ConsumerState {
+ late final TextEditingController searchController;
+ late final FocusNode searchFocus;
+
+ String _searchTerm = "";
+
+ @override
+ void initState() {
+ searchController = TextEditingController();
+ searchFocus = FocusNode();
+
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ searchController.dispose();
+ searchFocus.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Background(
+ child: SafeArea(
+ child: Scaffold(
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ appBar: AppBar(
+ automaticallyImplyLeading: false,
+ leading: const AppBarBackButton(),
+ title: Text(
+ "Ordinals",
+ style: STextStyles.navBarTitle(context),
+ ),
+ titleSpacing: 0,
+ actions: [
+ AspectRatio(
+ aspectRatio: 1,
+ child: AppBarIconButton(
+ size: 36,
+ icon: SvgPicture.asset(
+ Assets.svg.arrowRotate,
+ width: 20,
+ height: 20,
+ color: Theme.of(context)
+ .extension()!
+ .topNavIconPrimary,
+ ),
+ onPressed: () async {
+ // show loading for a minimum of 2 seconds on refreshing
+ await showLoading(
+ whileFuture: Future.wait([
+ Future.delayed(const Duration(seconds: 2)),
+ (ref
+ .read(walletsChangeNotifierProvider)
+ .getManager(widget.walletId)
+ .wallet as OrdinalsInterface)
+ .refreshInscriptions()
+ ]),
+ context: context,
+ message: "Refreshing...",
+ );
+ },
+ ),
+ ),
+ // AspectRatio(
+ // aspectRatio: 1,
+ // child: AppBarIconButton(
+ // size: 36,
+ // icon: SvgPicture.asset(
+ // Assets.svg.filter,
+ // width: 20,
+ // height: 20,
+ // color: Theme.of(context)
+ // .extension()!
+ // .topNavIconPrimary,
+ // ),
+ // onPressed: () {
+ // Navigator.of(context).pushNamed(
+ // OrdinalsFilterView.routeName,
+ // );
+ // },
+ // ),
+ // ),
+ ],
+ ),
+ body: Padding(
+ padding: const EdgeInsets.only(
+ left: 16,
+ right: 16,
+ top: 8,
+ ),
+ child: Column(
+ children: [
+ // ClipRRect(
+ // borderRadius: BorderRadius.circular(
+ // Constants.size.circularBorderRadius,
+ // ),
+ // child: TextField(
+ // autocorrect: Util.isDesktop ? false : true,
+ // enableSuggestions: Util.isDesktop ? false : true,
+ // controller: searchController,
+ // focusNode: searchFocus,
+ // onChanged: (value) {
+ // setState(() {
+ // _searchTerm = value;
+ // });
+ // },
+ // style: STextStyles.field(context),
+ // decoration: standardInputDecoration(
+ // "Search",
+ // searchFocus,
+ // context,
+ // ).copyWith(
+ // prefixIcon: Padding(
+ // padding: const EdgeInsets.symmetric(
+ // horizontal: 10,
+ // vertical: 16,
+ // ),
+ // child: SvgPicture.asset(
+ // Assets.svg.search,
+ // width: 16,
+ // height: 16,
+ // ),
+ // ),
+ // suffixIcon: searchController.text.isNotEmpty
+ // ? Padding(
+ // padding: const EdgeInsets.only(right: 0),
+ // child: UnconstrainedBox(
+ // child: Row(
+ // children: [
+ // TextFieldIconButton(
+ // child: const XIcon(),
+ // onTap: () async {
+ // setState(() {
+ // searchController.text = "";
+ // _searchTerm = "";
+ // });
+ // },
+ // ),
+ // ],
+ // ),
+ // ),
+ // )
+ // : null,
+ // ),
+ // ),
+ // ),
+ // const SizedBox(
+ // height: 16,
+ // ),
+ Expanded(
+ child: OrdinalsList(
+ walletId: widget.walletId,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/ordinals/widgets/dialogs.dart b/lib/pages/ordinals/widgets/dialogs.dart
new file mode 100644
index 000000000..ee5b57d33
--- /dev/null
+++ b/lib/pages/ordinals/widgets/dialogs.dart
@@ -0,0 +1,62 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:stackwallet/themes/stack_colors.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+import 'package:stackwallet/widgets/stack_dialog.dart';
+
+class SendOrdinalUnfreezeDialog extends StatelessWidget {
+ const SendOrdinalUnfreezeDialog({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return StackDialog(
+ title: "This ordinal is frozen",
+ icon: SvgPicture.asset(
+ Assets.svg.coinControl.blocked,
+ width: 24,
+ height: 24,
+ color: Theme.of(context).extension()!.textDark,
+ ),
+ message: "To send this ordinal, you must unfreeze it first.",
+ leftButton: SecondaryButton(
+ label: "Cancel",
+ onPressed: Navigator.of(context).pop,
+ ),
+ rightButton: PrimaryButton(
+ label: "Unfreeze",
+ onPressed: () {
+ Navigator.of(context).pop("unfreeze");
+ },
+ ),
+ );
+ }
+}
+
+class UnfreezeOrdinalDialog extends StatelessWidget {
+ const UnfreezeOrdinalDialog({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return StackDialog(
+ title: "Are you sure you want to unfreeze this ordinal?",
+ icon: SvgPicture.asset(
+ Assets.svg.coinControl.blocked,
+ width: 24,
+ height: 24,
+ color: Theme.of(context).extension()!.textDark,
+ ),
+ leftButton: SecondaryButton(
+ label: "Cancel",
+ onPressed: Navigator.of(context).pop,
+ ),
+ rightButton: PrimaryButton(
+ label: "Unfreeze",
+ onPressed: () {
+ Navigator.of(context).pop("unfreeze");
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/pages/ordinals/widgets/ordinal_card.dart b/lib/pages/ordinals/widgets/ordinal_card.dart
new file mode 100644
index 000000000..c74366d74
--- /dev/null
+++ b/lib/pages/ordinals/widgets/ordinal_card.dart
@@ -0,0 +1,63 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/models/isar/ordinal.dart';
+import 'package:stackwallet/pages/ordinals/ordinal_details_view.dart';
+import 'package:stackwallet/pages_desktop_specific/ordinals/desktop_ordinal_details_view.dart';
+import 'package:stackwallet/utilities/constants.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+class OrdinalCard extends StatelessWidget {
+ const OrdinalCard({
+ Key? key,
+ required this.walletId,
+ required this.ordinal,
+ }) : super(key: key);
+
+ final String walletId;
+ final Ordinal ordinal;
+
+ @override
+ Widget build(BuildContext context) {
+ return RoundedWhiteContainer(
+ radiusMultiplier: 2,
+ onPressed: () {
+ Navigator.of(context).pushNamed(
+ Util.isDesktop
+ ? DesktopOrdinalDetailsView.routeName
+ : OrdinalDetailsView.routeName,
+ arguments: (walletId: walletId, ordinal: ordinal),
+ );
+ },
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ AspectRatio(
+ aspectRatio: 1,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ child: Image.network(
+ ordinal.content, // Use the preview URL as the image source
+ fit: BoxFit.cover,
+ filterQuality:
+ FilterQuality.none, // Set the filter mode to nearest
+ ),
+ ),
+ ),
+ const Spacer(),
+ Text(
+ 'INSC. ${ordinal.inscriptionNumber}', // infer from address associated with utxoTXID
+ style: STextStyles.w500_12(context),
+ ),
+ // const Spacer(),
+ // Text(
+ // "ID ${ordinal.inscriptionId}",
+ // style: STextStyles.w500_8(context),
+ // ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/pages/ordinals/widgets/ordinals_list.dart b/lib/pages/ordinals/widgets/ordinals_list.dart
new file mode 100644
index 000000000..481b0ef0a
--- /dev/null
+++ b/lib/pages/ordinals/widgets/ordinals_list.dart
@@ -0,0 +1,119 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:isar/isar.dart';
+import 'package:stackwallet/models/isar/ordinal.dart';
+import 'package:stackwallet/pages/ordinals/widgets/ordinal_card.dart';
+import 'package:stackwallet/providers/db/main_db_provider.dart';
+import 'package:stackwallet/themes/stack_colors.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+
+class OrdinalsList extends ConsumerStatefulWidget {
+ const OrdinalsList({
+ Key? key,
+ required this.walletId,
+ }) : super(key: key);
+
+ final String walletId;
+
+ @override
+ ConsumerState createState() => _OrdinalsListState();
+}
+
+class _OrdinalsListState extends ConsumerState {
+ final double _spacing = Util.isDesktop ? 16 : 10;
+
+ late List _data;
+
+ late final Stream?> _stream;
+
+ @override
+ void initState() {
+ _stream = ref
+ .read(mainDBProvider)
+ .isar
+ .ordinals
+ .where()
+ .filter()
+ .walletIdEqualTo(widget.walletId)
+ .watch();
+
+ _data = ref
+ .read(mainDBProvider)
+ .isar
+ .ordinals
+ .where()
+ .filter()
+ .walletIdEqualTo(widget.walletId)
+ .findAllSync();
+
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return StreamBuilder