Account creation workflow... still need logic.
This commit is contained in:
@@ -2,8 +2,151 @@
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "7219ad348874b83380e4072dec332bee",
|
||||
"identityHash": "61eb893d34ad04f95f8b007f8448ad7f",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "BroadcastNostrEventReceipt",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nostrEventId` TEXT NOT NULL, `isAccepted` INTEGER NOT NULL, `relayURL` TEXT NOT NULL, `messages` TEXT, FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isAccepted",
|
||||
"columnName": "isAccepted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "relayURL",
|
||||
"columnName": "relayURL",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "messages",
|
||||
"columnName": "messages",
|
||||
"affinity": "TEXT"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_BroadcastNostrEventReceipt_nostrEventId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"nostrEventId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_BroadcastNostrEventReceipt_nostrEventId` ON `${TABLE_NAME}` (`nostrEventId`)"
|
||||
},
|
||||
{
|
||||
"name": "index_BroadcastNostrEventReceipt_isAccepted",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"isAccepted"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_BroadcastNostrEventReceipt_isAccepted` ON `${TABLE_NAME}` (`isAccepted`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "NostrEvent",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"nostrEventId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "BroadcastNostrEventRequest",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `nostrEventId` TEXT NOT NULL, `status` TEXT NOT NULL, `relayURL` TEXT NOT NULL, FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "status",
|
||||
"columnName": "status",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "relayURL",
|
||||
"columnName": "relayURL",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_BroadcastNostrEventRequest_nostrEventId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"nostrEventId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_BroadcastNostrEventRequest_nostrEventId` ON `${TABLE_NAME}` (`nostrEventId`)"
|
||||
},
|
||||
{
|
||||
"name": "index_BroadcastNostrEventRequest_status",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"status"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_BroadcastNostrEventRequest_status` ON `${TABLE_NAME}` (`status`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "NostrEvent",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"nostrEventId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "NostrEvent",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `sig` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`))",
|
||||
@@ -82,7 +225,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "Post",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `replyToId` TEXT, `repostId` TEXT, `quote` TEXT, `profilePublicKey` TEXT NOT NULL, `content` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`profilePublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`replyToId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`repostId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `repostId` TEXT, `quote` TEXT, `content` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `replyToId` TEXT, `profilePublicKey` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`profilePublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`replyToId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`repostId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@@ -90,6 +233,22 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "repostId",
|
||||
"columnName": "repostId",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "quote",
|
||||
"columnName": "quote",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
@@ -101,28 +260,12 @@
|
||||
"columnName": "replyToId",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "repostId",
|
||||
"columnName": "repostId",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "quote",
|
||||
"columnName": "quote",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "profilePublicKey",
|
||||
"columnName": "profilePublicKey",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdAt",
|
||||
"columnName": "createdAt",
|
||||
@@ -250,7 +393,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "Profile",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`publicKey` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `userName` TEXT, `displayName` TEXT, `picture` TEXT, `banner` TEXT, `website` TEXT, `about` TEXT, `bot` INTEGER, `pronouns` TEXT, `nip05` TEXT, `domain` TEXT, `lud06` TEXT, `lud16` TEXT, `twitter` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`publicKey`), FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`publicKey` TEXT NOT NULL, `userName` TEXT, `displayName` TEXT, `picture` TEXT, `banner` TEXT, `website` TEXT, `about` TEXT, `bot` INTEGER, `pronouns` TEXT, `nip05` TEXT, `domain` TEXT, `lud06` TEXT, `lud16` TEXT, `twitter` TEXT, `nostrEventId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`publicKey`), FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "publicKey",
|
||||
@@ -258,12 +401,6 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "userName",
|
||||
"columnName": "userName",
|
||||
@@ -329,6 +466,12 @@
|
||||
"columnName": "twitter",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdAt",
|
||||
"columnName": "createdAt",
|
||||
@@ -396,7 +539,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "Reaction",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `replyToId` TEXT NOT NULL, `profilePublicKey` TEXT NOT NULL, `content` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`profilePublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`replyToId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `content` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `replyToId` TEXT NOT NULL, `profilePublicKey` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`profilePublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`replyToId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@@ -404,6 +547,12 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
@@ -422,12 +571,6 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdAt",
|
||||
"columnName": "createdAt",
|
||||
@@ -535,7 +678,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "Repost",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `postId` TEXT, `profilePublicKey` TEXT NOT NULL, `content` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`profilePublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`postId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `repostedPostId` TEXT, `content` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `profilePublicKey` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`profilePublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`repostedPostId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@@ -543,29 +686,29 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "repostedPostId",
|
||||
"columnName": "repostedPostId",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "postId",
|
||||
"columnName": "postId",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "profilePublicKey",
|
||||
"columnName": "profilePublicKey",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdAt",
|
||||
"columnName": "createdAt",
|
||||
@@ -626,13 +769,13 @@
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_Repost_nostrEventId` ON `${TABLE_NAME}` (`nostrEventId`)"
|
||||
},
|
||||
{
|
||||
"name": "index_Repost_postId",
|
||||
"name": "index_Repost_repostedPostId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"postId"
|
||||
"repostedPostId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_Repost_postId` ON `${TABLE_NAME}` (`postId`)"
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_Repost_repostedPostId` ON `${TABLE_NAME}` (`repostedPostId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
@@ -663,7 +806,100 @@
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"postId"
|
||||
"repostedPostId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tableName": "UnsignedNostrEvent",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `signedNostrEventId` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, FOREIGN KEY(`signedNostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "kind",
|
||||
"columnName": "kind",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tags",
|
||||
"columnName": "tags",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "content",
|
||||
"columnName": "content",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "signedNostrEventId",
|
||||
"columnName": "signedNostrEventId",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdAt",
|
||||
"columnName": "createdAt",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "updatedAt",
|
||||
"columnName": "updatedAt",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "savedAt",
|
||||
"columnName": "savedAt",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deletedAt",
|
||||
"columnName": "deletedAt",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "broadcastedAt",
|
||||
"columnName": "broadcastedAt",
|
||||
"affinity": "INTEGER"
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [
|
||||
{
|
||||
"name": "index_UnsignedNostrEvent_signedNostrEventId",
|
||||
"unique": false,
|
||||
"columnNames": [
|
||||
"signedNostrEventId"
|
||||
],
|
||||
"orders": [],
|
||||
"createSql": "CREATE INDEX IF NOT EXISTS `index_UnsignedNostrEvent_signedNostrEventId` ON `${TABLE_NAME}` (`signedNostrEventId`)"
|
||||
}
|
||||
],
|
||||
"foreignKeys": [
|
||||
{
|
||||
"table": "NostrEvent",
|
||||
"onDelete": "CASCADE",
|
||||
"onUpdate": "NO ACTION",
|
||||
"columns": [
|
||||
"signedNostrEventId"
|
||||
],
|
||||
"referencedColumns": [
|
||||
"id"
|
||||
@@ -673,7 +909,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "Zap",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `nostrEventId` TEXT NOT NULL, `postId` TEXT NOT NULL, `senderPublicKey` TEXT NOT NULL, `receiverPublicKey` TEXT NOT NULL, `message` TEXT, `invoice` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`senderPublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`receiverPublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`postId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `postId` TEXT NOT NULL, `senderPublicKey` TEXT NOT NULL, `receiverPublicKey` TEXT NOT NULL, `message` TEXT, `invoice` TEXT, `amountInMillisatoshis` INTEGER, `nostrEventId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `viewedAt` INTEGER, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`), FOREIGN KEY(`senderPublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`receiverPublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`postId`) REFERENCES `Post`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@@ -681,12 +917,6 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "postId",
|
||||
"columnName": "postId",
|
||||
@@ -715,6 +945,17 @@
|
||||
"columnName": "invoice",
|
||||
"affinity": "TEXT"
|
||||
},
|
||||
{
|
||||
"fieldPath": "amountInMillisatoshis",
|
||||
"columnName": "amountInMillisatoshis",
|
||||
"affinity": "INTEGER"
|
||||
},
|
||||
{
|
||||
"fieldPath": "nostrEventId",
|
||||
"columnName": "nostrEventId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "createdAt",
|
||||
"columnName": "createdAt",
|
||||
@@ -834,7 +1075,7 @@
|
||||
],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7219ad348874b83380e4072dec332bee')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '61eb893d34ad04f95f8b007f8448ad7f')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,16 @@ import ac.aux.compose.database.dao.PostDao
|
||||
import ac.aux.compose.database.dao.ProfileDao
|
||||
import ac.aux.compose.database.dao.ReactionDao
|
||||
import ac.aux.compose.database.dao.RepostDao
|
||||
import ac.aux.compose.database.dao.UnsignedNostrEventDao
|
||||
import ac.aux.compose.database.dao.ZapDao
|
||||
import ac.aux.compose.database.model.BroadcastNostrEventReceipt
|
||||
import ac.aux.compose.database.model.BroadcastNostrEventRequest
|
||||
import ac.aux.compose.database.model.NostrEvent
|
||||
import ac.aux.compose.database.model.Post
|
||||
import ac.aux.compose.database.model.Profile
|
||||
import ac.aux.compose.database.model.Reaction
|
||||
import ac.aux.compose.database.model.Repost
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
import ac.aux.compose.database.model.Zap
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
@@ -22,11 +26,14 @@ import androidx.room.TypeConverters
|
||||
|
||||
@Database(
|
||||
entities = [
|
||||
BroadcastNostrEventReceipt::class,
|
||||
BroadcastNostrEventRequest::class,
|
||||
NostrEvent::class,
|
||||
Post::class,
|
||||
Profile::class,
|
||||
Reaction::class,
|
||||
Repost::class,
|
||||
UnsignedNostrEvent::class,
|
||||
Zap::class
|
||||
],
|
||||
version = 1
|
||||
@@ -42,5 +49,7 @@ abstract class AuxDatabase: RoomDatabase() {
|
||||
abstract fun profileDao(): ProfileDao
|
||||
abstract fun reactionDao(): ReactionDao
|
||||
abstract fun repostDao(): RepostDao
|
||||
|
||||
abstract fun unsignedNostrEventDao(): UnsignedNostrEventDao
|
||||
abstract fun zapDao(): ZapDao
|
||||
}
|
||||
@@ -20,5 +20,5 @@ interface UnsignedNostrEventDao {
|
||||
fun getUnsignedNostrEventById(id: Long): Flow<UnsignedNostrEvent?>
|
||||
|
||||
@Upsert
|
||||
suspend fun upsert(unsignedNostrEvent: UnsignedNostrEvent)
|
||||
suspend fun upsert(unsignedNostrEvent: UnsignedNostrEvent): Long
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import ac.aux.compose.database.model.traits.LocalStoreEntity
|
||||
import ac.aux.compose.database.model.traits.SoftDeletableEntity
|
||||
import ac.aux.compose.database.model.traits.TimestampedEntity
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
@@ -36,7 +37,8 @@ data class NostrEvent(
|
||||
override val deletedAt: Instant? = null,
|
||||
override val broadcastedAt: Instant? = null,
|
||||
): TimestampedEntity, LocalStoreEntity, BroadcastableEntity, SoftDeletableEntity {
|
||||
val logger = Logger.withTag("NostrEvent")
|
||||
@Ignore
|
||||
private val logger = Logger.withTag("NostrEvent")
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package ac.aux.compose.database.repository
|
||||
|
||||
import ac.aux.compose.database.AuxDatabase
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
class DatabaseNostrRepository(
|
||||
private val database: AuxDatabase
|
||||
): NostrRepository {
|
||||
|
||||
override suspend fun saveUnsignedNostrEvent(unsignedNostrEvent: UnsignedNostrEvent): UnsignedNostrEvent? = try {
|
||||
delay(2_100) // Just to make it look like we are doing serious work...
|
||||
unsignedNostrEvent.copy(
|
||||
id = database.unsignedNostrEventDao().upsert(unsignedNostrEvent)
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package ac.aux.compose.repository
|
||||
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
|
||||
interface NostrRepository {
|
||||
suspend fun saveUnsignedNostrEvent(unsignedNostrEvent: UnsignedNostrEvent): UnsignedNostrEvent?
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
package ac.aux.compose.ui.composable
|
||||
|
||||
import ac.aux.compose.database.model.Profile
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import ac.aux.compose.ui.composable.widgets.LoadingDataIndicator
|
||||
import ac.aux.compose.ui.theme.AuxTheme
|
||||
import ac.aux.compose.ui.theme.BluePill
|
||||
import ac.aux.compose.ui.theme.RedPill
|
||||
import ac.aux.compose.ui.view.model.CreateProfileViewModel
|
||||
import ac.aux.compose.ui.view.state.CreateProfileUIState
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -14,7 +20,11 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Badge
|
||||
import androidx.compose.material.icons.filled.Description
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LoadingIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
@@ -23,20 +33,25 @@ import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun CreateProfileScreen(
|
||||
initialCreateProfileUIState: CreateProfileUIState = CreateProfileUIState.Declaration,
|
||||
onNavigateToChatListRoute: () -> Unit
|
||||
onNavigateToSocialPreconditionRoute: () -> Unit,
|
||||
onEndThis: () -> Unit,
|
||||
nostrRepository: NostrRepository
|
||||
) {
|
||||
val createProfileViewModel: CreateProfileViewModel = viewModel (
|
||||
factory = CreateProfileViewModel.factory(
|
||||
initialCreateProfileUIState
|
||||
initialCreateProfileUIState,
|
||||
nostrRepository
|
||||
)
|
||||
)
|
||||
Scaffold { innerPadding ->
|
||||
@@ -191,11 +206,17 @@ fun CreateProfileScreen(
|
||||
Button(
|
||||
onClick = {
|
||||
|
||||
createProfileViewModel.createProfileUIState.value =
|
||||
CreateProfileUIState.ConfirmInput(
|
||||
name = createProfileViewModel.createProfileFormState.nameField.text.value,
|
||||
bio = createProfileViewModel.createProfileFormState.biographyField.text.value
|
||||
)
|
||||
createProfileViewModel.validateInput().let { isInputValid ->
|
||||
if (isInputValid) {
|
||||
createProfileViewModel.createProfileUIState.value =
|
||||
CreateProfileUIState.ConfirmInput(
|
||||
name = createProfileViewModel.createProfileFormState.nameField.text.value,
|
||||
bio = createProfileViewModel.createProfileFormState.biographyField.text.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
@@ -245,13 +266,135 @@ fun CreateProfileScreen(
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
if (createProfileViewModel.isActionPending.value) {
|
||||
LoadingIndicator(
|
||||
modifier = Modifier
|
||||
)
|
||||
} else {
|
||||
Button(
|
||||
onClick = {
|
||||
createProfileViewModel.createAccount()
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = "Create Profile"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
is CreateProfileUIState.Error -> {
|
||||
Spacer(
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = "Something went wrong and we were unable to sign you up. Please try again later.",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
}
|
||||
is CreateProfileUIState.UnsignedProfile -> {
|
||||
Spacer(
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = "Your profile is almost ready... just getting it's first cryptographic signature together.",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "As long as you control your keys there can be no dispute about who ${createAccountUIState.name} actually is.",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
LoadingDataIndicator(
|
||||
fillScreen = false
|
||||
)
|
||||
|
||||
Spacer(
|
||||
modifier = Modifier.weight(2f)
|
||||
)
|
||||
}
|
||||
is CreateProfileUIState.UnbroadcastedProfile -> {
|
||||
Spacer(
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = "Everything is cryptographical sound. Just announcing your profile to the world.",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "Aux will be broadcast to what you publish to relays so that it's distributed and decentralized.",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
LoadingDataIndicator(
|
||||
fillScreen = false
|
||||
)
|
||||
|
||||
Spacer(
|
||||
modifier = Modifier.weight(2f)
|
||||
)
|
||||
}
|
||||
is CreateProfileUIState.ProfileReady -> {
|
||||
|
||||
Spacer(
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = "Profile is ready",
|
||||
style = MaterialTheme.typography.headlineLarge,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "After this there is no turning back."
|
||||
)
|
||||
|
||||
Button(
|
||||
onClick = onNavigateToChatListRoute
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = RedPill,
|
||||
contentColor = Color.White
|
||||
),
|
||||
onClick = {
|
||||
|
||||
onNavigateToSocialPreconditionRoute.invoke()
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = "Create Profile"
|
||||
text = "See how deep the rabbit hole goes"
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(
|
||||
modifier = Modifier.padding(20.dp)
|
||||
)
|
||||
|
||||
Button(
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = BluePill,
|
||||
contentColor = Color.DarkGray
|
||||
),
|
||||
onClick = {
|
||||
// TODO: Delete everything and close the app
|
||||
onEndThis.invoke()
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = "end this"
|
||||
)
|
||||
}
|
||||
Spacer(
|
||||
modifier = Modifier.weight(2f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,13 +413,48 @@ fun CreateAccountScreenPreview() {
|
||||
) {
|
||||
CreateProfileScreen(
|
||||
initialCreateProfileUIState =
|
||||
// CreateProfileUIState.InputPrompt
|
||||
CreateProfileUIState.ConfirmInput(
|
||||
name = "Alan Turing",
|
||||
bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider."
|
||||
// CreateProfileUIState.InputPrompt,
|
||||
// CreateProfileUIState.Error,
|
||||
// CreateProfileUIState.ConfirmInput(
|
||||
// name = "Alan Turing",
|
||||
// bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider."
|
||||
// ),
|
||||
// CreateProfileUIState.UnsignedProfile(
|
||||
// unsignedNostrEvent = UnsignedNostrEvent(
|
||||
// kind = 0,
|
||||
// content = "Something here",
|
||||
// tags = emptyArray(),
|
||||
// ),
|
||||
// name = "Alan Turing",
|
||||
// bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider."
|
||||
// ),
|
||||
// CreateProfileUIState.UnbroadcastedProfile(
|
||||
// nostrEvent = NostrEvent(
|
||||
// id = "",
|
||||
// pubKey = "",
|
||||
// kind = 0,
|
||||
// content = "Something here",
|
||||
// tags = emptyArray(),
|
||||
// sig = ""
|
||||
// ),
|
||||
// name = "Alan Turing",
|
||||
// bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider."
|
||||
// ),
|
||||
CreateProfileUIState.ProfileReady(
|
||||
profile = Profile(
|
||||
publicKey = "",
|
||||
nostrEventId = "",
|
||||
displayName = "Alan Turing",
|
||||
about = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider."
|
||||
)
|
||||
),
|
||||
onNavigateToChatListRoute = {}
|
||||
)
|
||||
onNavigateToSocialPreconditionRoute = {},
|
||||
onEndThis = {},
|
||||
nostrRepository = object : NostrRepository {
|
||||
override suspend fun saveUnsignedNostrEvent(unsignedNostrEvent: UnsignedNostrEvent): UnsignedNostrEvent? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ fun SocialPreconditionScreen(
|
||||
)
|
||||
|
||||
Text(
|
||||
"Tell friends to join you on Aux so your feed stays lively and fresh.",
|
||||
"Tell friends to join you so your feed stays lively and fresh.",
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package ac.aux.compose.ui.composable.navigation
|
||||
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import ac.aux.compose.ui.composable.CreateProfileScreen
|
||||
import ac.aux.compose.ui.composable.FeedScreen
|
||||
import ac.aux.compose.ui.composable.ImplementationPendingScreen
|
||||
import ac.aux.compose.ui.composable.LandingScreen
|
||||
import ac.aux.compose.ui.composable.SocialPreconditionScreen
|
||||
import ac.aux.compose.ui.composable.navigation.routes.BlankRoute
|
||||
import ac.aux.compose.ui.composable.navigation.routes.CreateProfileRoute
|
||||
import ac.aux.compose.ui.composable.navigation.routes.FeedRoute
|
||||
import ac.aux.compose.ui.composable.navigation.routes.ImplementationPendingRoute
|
||||
@@ -18,6 +21,12 @@ import ac.aux.compose.ui.composable.navigation.routes.Route
|
||||
import ac.aux.compose.ui.composable.navigation.routes.SocialPreconditionRoute
|
||||
import ac.aux.compose.ui.composable.widgets.feed.DUMMY_EVENTS
|
||||
import ac.aux.compose.ui.view.state.FeedListUIState
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
fun AuxNavHost(
|
||||
@@ -50,12 +59,25 @@ fun AuxNavHost(
|
||||
}
|
||||
composable<CreateProfileRoute> {
|
||||
CreateProfileScreen(
|
||||
onNavigateToChatListRoute = {
|
||||
onNavigateToSocialPreconditionRoute = {
|
||||
navController.navigate(
|
||||
route = SocialPreconditionRoute
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
onEndThis = {
|
||||
// TODO: Delete everything and close the app
|
||||
navController.navigate(
|
||||
route = BlankRoute
|
||||
) {
|
||||
popUpTo(0)
|
||||
}
|
||||
},
|
||||
nostrRepository = object : NostrRepository {
|
||||
override suspend fun saveUnsignedNostrEvent(unsignedNostrEvent: UnsignedNostrEvent): UnsignedNostrEvent? {
|
||||
delay(2_100)
|
||||
return unsignedNostrEvent
|
||||
}
|
||||
})
|
||||
}
|
||||
composable<SocialPreconditionRoute> {
|
||||
SocialPreconditionScreen(
|
||||
@@ -90,6 +112,15 @@ fun AuxNavHost(
|
||||
}
|
||||
)
|
||||
}
|
||||
composable<BlankRoute> {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = Color.Black
|
||||
) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
composable<ImplementationPendingRoute> { backStackEntry ->
|
||||
val route: ImplementationPendingRoute = backStackEntry.toRoute()
|
||||
ImplementationPendingScreen(
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package ac.aux.compose.ui.composable.navigation.routes
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
object BlankRoute: Route()
|
||||
@@ -2,6 +2,9 @@ package ac.aux.compose.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val BluePill = Color(0xFF5D8DD6)
|
||||
val RedPill = Color(230, 32, 32, 191)
|
||||
|
||||
val primaryLight = Color(0xFF000000)
|
||||
val onPrimaryLight = Color(0xFFFFFFFF)
|
||||
val primaryContainerLight = Color(0xFF1B1B1B)
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package ac.aux.compose.ui.view.model
|
||||
|
||||
import ac.aux.compose.database.model.NostrEvent
|
||||
import ac.aux.compose.database.model.Profile
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import ac.aux.compose.ui.view.state.CreateProfileUIState
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -8,21 +12,31 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import ac.aux.compose.ui.view.state.form.CreateProfileFormState
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.IO
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.time.Instant
|
||||
|
||||
class CreateProfileViewModel(
|
||||
val initialCreateProfileUIState: CreateProfileUIState,
|
||||
val createProfileFormState: CreateProfileFormState = CreateProfileFormState(),
|
||||
val nostrRepository: NostrRepository
|
||||
): ViewModel() {
|
||||
companion object {
|
||||
private const val TAG = "CreateAccountViewModel"
|
||||
|
||||
fun factory(
|
||||
initialCreateProfileUIState: CreateProfileUIState
|
||||
initialCreateProfileUIState: CreateProfileUIState,
|
||||
nostrRepository: NostrRepository
|
||||
): ViewModelProvider.Factory = viewModelFactory {
|
||||
initializer {
|
||||
CreateProfileViewModel(
|
||||
initialCreateProfileUIState
|
||||
initialCreateProfileUIState,
|
||||
nostrRepository = nostrRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -36,11 +50,82 @@ class CreateProfileViewModel(
|
||||
initialCreateProfileUIState
|
||||
)
|
||||
|
||||
public fun createAccount(
|
||||
onSuccess: () -> Unit,
|
||||
onFailure: () -> Unit
|
||||
) {
|
||||
fun validateInput(): Boolean {
|
||||
if (createProfileFormState.nameField.text.value.isBlank()) {
|
||||
createProfileFormState.nameField.errorMessage.value = "Please input a display name"
|
||||
return false
|
||||
} else {
|
||||
createProfileFormState.nameField.errorMessage.value = null
|
||||
}
|
||||
|
||||
if (createProfileFormState.biographyField.text.value.isBlank()) {
|
||||
createProfileFormState.biographyField.errorMessage.value = "Please input a biography"
|
||||
return false
|
||||
} else {
|
||||
createProfileFormState.biographyField.errorMessage.value = null
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public fun createAccount() {
|
||||
logger.d { "createAccount" }
|
||||
onFailure.invoke()
|
||||
isActionPending.value = true
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
|
||||
val profileEventTemplate = MetadataEvent.createNew(
|
||||
name = createProfileFormState.nameField.text.value,
|
||||
about = createProfileFormState.biographyField.text.value
|
||||
)
|
||||
|
||||
val unsignedNostrEvent = nostrRepository.saveUnsignedNostrEvent(
|
||||
UnsignedNostrEvent(
|
||||
kind = profileEventTemplate.kind,
|
||||
createdAt = Instant.fromEpochMilliseconds(profileEventTemplate.createdAt),
|
||||
tags = profileEventTemplate.tags,
|
||||
content = profileEventTemplate.content
|
||||
)
|
||||
)
|
||||
|
||||
isActionPending.value = false
|
||||
|
||||
if (unsignedNostrEvent != null) {
|
||||
createProfileUIState.value = CreateProfileUIState.UnsignedProfile(
|
||||
unsignedNostrEvent = unsignedNostrEvent,
|
||||
name = createProfileFormState.nameField.text.value,
|
||||
bio = createProfileFormState.biographyField.text.value
|
||||
)
|
||||
|
||||
delay(7_500) // Seeming busy is very important...
|
||||
|
||||
createProfileUIState.value = CreateProfileUIState.UnbroadcastedProfile(
|
||||
nostrEvent = NostrEvent(
|
||||
id = "",
|
||||
pubKey = "",
|
||||
kind = 0,
|
||||
content = "Something here",
|
||||
tags = emptyArray(),
|
||||
sig = ""
|
||||
),
|
||||
name = createProfileFormState.nameField.text.value,
|
||||
bio = createProfileFormState.biographyField.text.value
|
||||
)
|
||||
|
||||
delay(4_500) // Seeming busy is very important...
|
||||
|
||||
createProfileUIState.value = CreateProfileUIState.ProfileReady(
|
||||
profile = Profile(
|
||||
publicKey = "",
|
||||
nostrEventId = "",
|
||||
displayName = createProfileFormState.nameField.text.value,
|
||||
about = createProfileFormState.biographyField.text.value,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
createProfileUIState.value = CreateProfileUIState.Error
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
package ac.aux.compose.ui.view.state
|
||||
|
||||
import ac.aux.compose.database.model.NostrEvent
|
||||
import ac.aux.compose.database.model.Profile
|
||||
import ac.aux.compose.database.model.UnsignedNostrEvent
|
||||
|
||||
abstract class CreateProfileUIState {
|
||||
data object Error: CreateProfileUIState()
|
||||
|
||||
data object Declaration: CreateProfileUIState()
|
||||
|
||||
@@ -10,4 +15,20 @@ abstract class CreateProfileUIState {
|
||||
val name: String,
|
||||
val bio: String
|
||||
) : CreateProfileUIState()
|
||||
|
||||
data class UnsignedProfile(
|
||||
val unsignedNostrEvent: UnsignedNostrEvent,
|
||||
val name: String,
|
||||
val bio: String,
|
||||
) : CreateProfileUIState()
|
||||
|
||||
data class UnbroadcastedProfile(
|
||||
val nostrEvent: NostrEvent,
|
||||
val name: String,
|
||||
val bio: String
|
||||
) : CreateProfileUIState()
|
||||
|
||||
data class ProfileReady(
|
||||
val profile: Profile
|
||||
) : CreateProfileUIState()
|
||||
}
|
||||
Reference in New Issue
Block a user