chore: added restore from backup to homepage
02bc5284
2 file(s) · +76 −21
| 15 | 15 | extractPostContent, |
|
| 16 | 16 | extractPostDate, |
|
| 17 | 17 | } from "@/lib/feed-operations"; |
|
| 18 | + | import { |
|
| 19 | + | Dialog, |
|
| 20 | + | DialogContent, |
|
| 21 | + | DialogDescription, |
|
| 22 | + | DialogHeader, |
|
| 23 | + | DialogTitle, |
|
| 24 | + | } from "@/components/ui/dialog"; |
|
| 25 | + | import { Upload } from "lucide-react"; |
|
| 26 | + | import { Mnemonic } from "@evolu/common"; |
|
| 18 | 27 | ||
| 19 | 28 | function App() { |
|
| 20 | 29 | const allFeeds = useQuery(allFeedsQuery); |
|
| 22 | 31 | const [urlInput, setUrlInput] = React.useState(""); |
|
| 23 | 32 | const [isAddingFeed, setIsAddingFeed] = React.useState(false); |
|
| 24 | 33 | const [errorMessage, setErrorMessage] = React.useState(""); |
|
| 34 | + | const [isRestoreDialogOpen, setIsRestoreDialogOpen] = React.useState(false); |
|
| 35 | + | const [restoreMnemonic, setRestoreMnemonic] = React.useState(""); |
|
| 25 | 36 | ||
| 26 | 37 | const evolu = useEvolu(); |
|
| 38 | + | ||
| 39 | + | function handleRestoreDialogOpenChange(open: boolean) { |
|
| 40 | + | setIsRestoreDialogOpen(open); |
|
| 41 | + | if (!open) { |
|
| 42 | + | setRestoreMnemonic(""); |
|
| 43 | + | } |
|
| 44 | + | } |
|
| 45 | + | ||
| 46 | + | function handleRestore() { |
|
| 47 | + | if (restoreMnemonic.trim()) { |
|
| 48 | + | evolu.restoreAppOwner(restoreMnemonic as Mnemonic); |
|
| 49 | + | setIsRestoreDialogOpen(false); |
|
| 50 | + | setRestoreMnemonic(""); |
|
| 51 | + | toast.success("Account restored successfully"); |
|
| 52 | + | } |
|
| 53 | + | } |
|
| 27 | 54 | ||
| 28 | 55 | async function addFeed() { |
|
| 29 | 56 | if (!urlInput.trim()) { |
|
| 132 | 159 | {errorMessage} |
|
| 133 | 160 | </div> |
|
| 134 | 161 | )} |
|
| 162 | + | <Button |
|
| 163 | + | variant="outline" |
|
| 164 | + | onClick={() => setIsRestoreDialogOpen(true)} |
|
| 165 | + | className="w-full" |
|
| 166 | + | > |
|
| 167 | + | <Upload className="h-4 w-4 mr-2" /> |
|
| 168 | + | Restore from Backup |
|
| 169 | + | </Button> |
|
| 135 | 170 | </div> |
|
| 136 | 171 | </div> |
|
| 137 | 172 | )} |
|
| 173 | + | <Dialog |
|
| 174 | + | open={isRestoreDialogOpen} |
|
| 175 | + | onOpenChange={handleRestoreDialogOpenChange} |
|
| 176 | + | > |
|
| 177 | + | <DialogContent> |
|
| 178 | + | <DialogHeader> |
|
| 179 | + | <DialogTitle>Restore from Backup</DialogTitle> |
|
| 180 | + | <DialogDescription> |
|
| 181 | + | Enter your backup phrase to restore your account and access your |
|
| 182 | + | encrypted data. |
|
| 183 | + | </DialogDescription> |
|
| 184 | + | </DialogHeader> |
|
| 185 | + | <div className="space-y-4"> |
|
| 186 | + | <textarea |
|
| 187 | + | className="w-full p-4 bg-muted rounded-lg font-mono text-sm resize-none min-h-[100px]" |
|
| 188 | + | placeholder="Enter your backup phrase here..." |
|
| 189 | + | value={restoreMnemonic} |
|
| 190 | + | onChange={(e) => setRestoreMnemonic(e.target.value)} |
|
| 191 | + | /> |
|
| 192 | + | <Button |
|
| 193 | + | onClick={handleRestore} |
|
| 194 | + | disabled={!restoreMnemonic.trim()} |
|
| 195 | + | className="w-full" |
|
| 196 | + | > |
|
| 197 | + | <Upload className="h-4 w-4 mr-2" /> |
|
| 198 | + | Restore Account |
|
| 199 | + | </Button> |
|
| 200 | + | </div> |
|
| 201 | + | </DialogContent> |
|
| 202 | + | </Dialog> |
|
| 138 | 203 | </main> |
|
| 139 | 204 | ); |
|
| 140 | 205 | } |
|
| 1 | - | import * as Evolu from "@evolu/common"; |
|
| 2 | 1 | import { evoluReactWebDeps } from "@evolu/react-web"; |
|
| 3 | 2 | import { Schema, type RSSFeedId } from "./scheme.ts"; |
|
| 4 | 3 | import { createUseEvolu } from "@evolu/react"; |
|
| 5 | - | ||
| 6 | - | const service = "alcove"; |
|
| 7 | - | ||
| 8 | - | // Initialize authentication |
|
| 9 | - | const authResult = await evoluReactWebDeps.localAuth.login(undefined, { |
|
| 10 | - | service, |
|
| 11 | - | }); |
|
| 4 | + | import { createEvolu, SimpleName, sqliteTrue } from "@evolu/common"; |
|
| 12 | 5 | ||
| 13 | - | export const evolu = Evolu.createEvolu(evoluReactWebDeps)(Schema, { |
|
| 14 | - | name: Evolu.SimpleName.orThrow( |
|
| 15 | - | `${service}-${authResult?.owner?.id ?? "guest"}`, |
|
| 16 | - | ), |
|
| 6 | + | export const evolu = createEvolu(evoluReactWebDeps)(Schema, { |
|
| 7 | + | name: SimpleName.orThrow("alcove"), |
|
| 17 | 8 | reloadUrl: "/", |
|
| 18 | - | encryptionKey: authResult?.owner?.encryptionKey, |
|
| 19 | - | externalAppOwner: authResult?.owner, |
|
| 20 | 9 | transports: [ |
|
| 21 | 10 | { |
|
| 22 | 11 | type: "WebSocket", |
|
| 23 | 12 | url: "wss://relay.alcove.tools", |
|
| 24 | 13 | }, |
|
| 14 | + | // { |
|
| 15 | + | // type: "WebSocket", |
|
| 16 | + | // url: "ws://localhost:4000", |
|
| 17 | + | // }, |
|
| 25 | 18 | ], |
|
| 26 | 19 | }); |
|
| 27 | 20 | ||
| 38 | 31 | }); |
|
| 39 | 32 | ||
| 40 | 33 | export const allFeedsQuery = evolu.createQuery((db) => |
|
| 41 | - | db |
|
| 42 | - | .selectFrom("rssFeed") |
|
| 43 | - | .selectAll() |
|
| 44 | - | .where("isDeleted", "is not", Evolu.sqliteTrue), |
|
| 34 | + | db.selectFrom("rssFeed").selectAll().where("isDeleted", "is not", sqliteTrue), |
|
| 45 | 35 | ); |
|
| 46 | 36 | ||
| 47 | 37 | export const postsByFeedQuery = (feedId: string) => |
|
| 50 | 40 | .selectFrom("rssPost") |
|
| 51 | 41 | .selectAll() |
|
| 52 | 42 | .where("feedId", "=", feedId as RSSFeedId) |
|
| 53 | - | .where("isDeleted", "is not", Evolu.sqliteTrue) |
|
| 43 | + | .where("isDeleted", "is not", sqliteTrue) |
|
| 54 | 44 | .orderBy("id", "desc"), |
|
| 55 | 45 | ); |
|
| 56 | 46 | ||
| 58 | 48 | db |
|
| 59 | 49 | .selectFrom("rssPost") |
|
| 60 | 50 | .selectAll() |
|
| 61 | - | .where("isDeleted", "is not", Evolu.sqliteTrue) |
|
| 51 | + | .where("isDeleted", "is not", sqliteTrue) |
|
| 62 | 52 | .orderBy("id", "desc"), |
|
| 63 | 53 | ); |
|
| 64 | 54 | ||
| 66 | 56 | db |
|
| 67 | 57 | .selectFrom("rssFeed") |
|
| 68 | 58 | .selectAll() |
|
| 69 | - | .where("isDeleted", "is not", Evolu.sqliteTrue) |
|
| 59 | + | .where("isDeleted", "is not", sqliteTrue) |
|
| 70 | 60 | .orderBy("category", "asc"), |
|
| 71 | 61 | ); |
|
| 72 | 62 | ||