From 3afb3113be45be519d7ef88db1cb7254fed5d26e Mon Sep 17 00:00:00 2001 From: Owais Jamil Date: Fri, 2 Jan 2026 01:22:57 -0600 Subject: [PATCH] refactor: Update lexicon namespaces * add `card_type` database column * put animations back in tutorial overlay --- crates/core/src/at_uri.rs | 41 ++++++++++--------- crates/server/src/repository/card.rs | 21 ++++++---- docs/at-notes.md | 2 +- docs/data-model-mapping.md | 28 ++++++------- docs/information-architecture.md | 20 ++++----- docs/share-vs-private-rules.md | 14 +++---- docs/todo.md | 2 +- lexicons/README.md | 16 ++++---- .../stormlightlabs}/malfestio/card.json | 2 +- .../stormlightlabs}/malfestio/collection.json | 2 +- .../stormlightlabs}/malfestio/deck.json | 2 +- .../stormlightlabs}/malfestio/note.json | 2 +- .../malfestio/source/article.json | 2 +- .../malfestio/source/lecture.json | 2 +- .../malfestio/thread/comment.json | 2 +- migrations/012_2026_01_02_add_card_type.sql | 5 +++ web/src/components/TutorialOverlay.tsx | 40 ++++++++++-------- web/src/components/tests/DeckPreview.test.tsx | 4 +- web/src/components/tests/Library.test.tsx | 2 +- 19 files changed, 114 insertions(+), 95 deletions(-) rename lexicons/{app => org/stormlightlabs}/malfestio/card.json (97%) rename lexicons/{app => org/stormlightlabs}/malfestio/collection.json (95%) rename lexicons/{app => org/stormlightlabs}/malfestio/deck.json (96%) rename lexicons/{app => org/stormlightlabs}/malfestio/note.json (97%) rename lexicons/{app => org/stormlightlabs}/malfestio/source/article.json (96%) rename lexicons/{app => org/stormlightlabs}/malfestio/source/lecture.json (96%) rename lexicons/{app => org/stormlightlabs}/malfestio/thread/comment.json (92%) create mode 100644 migrations/012_2026_01_02_add_card_type.sql diff --git a/crates/core/src/at_uri.rs b/crates/core/src/at_uri.rs index 70cf8cf..6fde726 100644 --- a/crates/core/src/at_uri.rs +++ b/crates/core/src/at_uri.rs @@ -4,7 +4,7 @@ //! Format: `at:////` //! //! - authority: DID or handle -//! - collection: NSID (e.g., "app.malfestio.deck") +//! - collection: NSID (e.g., "org.stormlightlabs.malfestio.deck") //! - rkey: Record key (usually a TID) use std::fmt; @@ -14,7 +14,7 @@ use std::fmt; pub struct AtUri { /// The authority (DID or handle) pub authority: String, - /// The collection NSID (e.g., "app.malfestio.deck") + /// The collection NSID (e.g., "org.stormlightlabs.malfestio.deck") pub collection: String, /// The record key pub rkey: String, @@ -34,17 +34,17 @@ impl AtUri { /// Create an AT-URI for a deck record. pub fn deck(did: &str, rkey: &str) -> Self { - Self::new(did, "app.malfestio.deck", rkey) + Self::new(did, "org.stormlightlabs.malfestio.deck", rkey) } /// Create an AT-URI for a card record. pub fn card(did: &str, rkey: &str) -> Self { - Self::new(did, "app.malfestio.card", rkey) + Self::new(did, "org.stormlightlabs.malfestio.card", rkey) } /// Create an AT-URI for a note record. pub fn note(did: &str, rkey: &str) -> Self { - Self::new(did, "app.malfestio.note", rkey) + Self::new(did, "org.stormlightlabs.malfestio.note", rkey) } /// Parse an AT-URI string. @@ -126,29 +126,32 @@ mod tests { #[test] fn test_new_at_uri() { - let uri = AtUri::new("did:plc:abc123", "app.malfestio.deck", "3k5abc123"); + let uri = AtUri::new("did:plc:abc123", "org.stormlightlabs.malfestio.deck", "3k5abc123"); assert_eq!(uri.authority, "did:plc:abc123"); - assert_eq!(uri.collection, "app.malfestio.deck"); + assert_eq!(uri.collection, "org.stormlightlabs.malfestio.deck"); assert_eq!(uri.rkey, "3k5abc123"); } #[test] fn test_display() { - let uri = AtUri::new("did:plc:abc123", "app.malfestio.deck", "3k5abc123"); - assert_eq!(uri.to_string(), "at://did:plc:abc123/app.malfestio.deck/3k5abc123"); + let uri = AtUri::new("did:plc:abc123", "org.stormlightlabs.malfestio.deck", "3k5abc123"); + assert_eq!( + uri.to_string(), + "at://did:plc:abc123/org.stormlightlabs.malfestio.deck/3k5abc123" + ); } #[test] fn test_parse_valid() { - let uri = AtUri::parse("at://did:plc:abc123/app.malfestio.deck/3k5abc123").unwrap(); + let uri = AtUri::parse("at://did:plc:abc123/org.stormlightlabs.malfestio.deck/3k5abc123").unwrap(); assert_eq!(uri.authority, "did:plc:abc123"); - assert_eq!(uri.collection, "app.malfestio.deck"); + assert_eq!(uri.collection, "org.stormlightlabs.malfestio.deck"); assert_eq!(uri.rkey, "3k5abc123"); } #[test] fn test_parse_with_handle() { - let uri = AtUri::parse("at://alice.bsky.social/app.malfestio.note/abc123").unwrap(); + let uri = AtUri::parse("at://alice.bsky.social/org.stormlightlabs.malfestio.note/abc123").unwrap(); assert_eq!(uri.authority, "alice.bsky.social"); assert!(uri.is_handle()); assert!(!uri.is_did()); @@ -156,19 +159,19 @@ mod tests { #[test] fn test_parse_missing_scheme() { - let result = AtUri::parse("did:plc:abc123/app.malfestio.deck/3k5abc123"); + let result = AtUri::parse("did:plc:abc123/org.stormlightlabs.malfestio.deck/3k5abc123"); assert_eq!(result, Err(AtUriError::MissingScheme)); } #[test] fn test_parse_invalid_format() { - let result = AtUri::parse("at://did:plc:abc123/app.malfestio.deck"); + let result = AtUri::parse("at://did:plc:abc123/org.stormlightlabs.malfestio.deck"); assert_eq!(result, Err(AtUriError::InvalidFormat)); } #[test] fn test_parse_empty_authority() { - let result = AtUri::parse("at:///app.malfestio.deck/rkey"); + let result = AtUri::parse("at:///org.stormlightlabs.malfestio.deck/rkey"); assert_eq!(result, Err(AtUriError::EmptyAuthority)); } @@ -180,7 +183,7 @@ mod tests { #[test] fn test_roundtrip() { - let original = "at://did:plc:abc123/app.malfestio.deck/3k5abc123"; + let original = "at://did:plc:abc123/org.stormlightlabs.malfestio.deck/3k5abc123"; let uri = AtUri::parse(original).unwrap(); assert_eq!(uri.to_string(), original); } @@ -188,13 +191,13 @@ mod tests { #[test] fn test_convenience_constructors() { let deck = AtUri::deck("did:plc:abc", "tid123"); - assert_eq!(deck.collection, "app.malfestio.deck"); + assert_eq!(deck.collection, "org.stormlightlabs.malfestio.deck"); let card = AtUri::card("did:plc:abc", "tid456"); - assert_eq!(card.collection, "app.malfestio.card"); + assert_eq!(card.collection, "org.stormlightlabs.malfestio.card"); let note = AtUri::note("did:plc:abc", "tid789"); - assert_eq!(note.collection, "app.malfestio.note"); + assert_eq!(note.collection, "org.stormlightlabs.malfestio.note"); } #[test] diff --git a/crates/server/src/repository/card.rs b/crates/server/src/repository/card.rs index bca3bdb..5904ade 100644 --- a/crates/server/src/repository/card.rs +++ b/crates/server/src/repository/card.rs @@ -23,11 +23,8 @@ pub struct CreateCardParams { #[async_trait] pub trait CardRepository: Send + Sync { async fn create(&self, params: CreateCardParams) -> Result; - async fn list_by_deck(&self, deck_id: &str) -> Result, CardRepoError>; - async fn verify_deck_ownership(&self, deck_id: &str, owner_did: &str) -> Result; - async fn update_at_uri(&self, card_id: &str, at_uri: &str) -> Result<(), CardRepoError>; } @@ -67,10 +64,14 @@ impl CardRepository for DbCardRepository { } let card_id = uuid::Uuid::new_v4(); + let card_type_str = match params.card_type { + CardType::Basic => "basic", + CardType::Cloze => "cloze", + }; client .execute( - "INSERT INTO cards (id, owner_did, deck_id, front, back, media_url, hints) - VALUES ($1, $2, $3, $4, $5, $6, $7)", + "INSERT INTO cards (id, owner_did, deck_id, front, back, media_url, hints, card_type) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", &[ &card_id, ¶ms.owner_did, @@ -79,6 +80,7 @@ impl CardRepository for DbCardRepository { ¶ms.back, ¶ms.media_url, ¶ms.hints, + &card_type_str, ], ) .await @@ -118,7 +120,7 @@ impl CardRepository for DbCardRepository { let rows = client .query( - "SELECT id, owner_did, deck_id, front, back, media_url, hints + "SELECT id, owner_did, deck_id, front, back, media_url, hints, card_type FROM cards WHERE deck_id = $1 ORDER BY created_at ASC", @@ -131,6 +133,11 @@ impl CardRepository for DbCardRepository { for row in rows { let id: uuid::Uuid = row.get("id"); let card_deck_id: uuid::Uuid = row.get("deck_id"); + let card_type_str: Option = row.get("card_type"); + let card_type = match card_type_str.as_deref() { + Some("cloze") => CardType::Cloze, + _ => CardType::Basic, + }; cards.push(Card { id: id.to_string(), @@ -139,7 +146,7 @@ impl CardRepository for DbCardRepository { front: row.get("front"), back: row.get("back"), media_url: row.get("media_url"), - card_type: CardType::default(), + card_type, hints: row.get("hints"), }); } diff --git a/docs/at-notes.md b/docs/at-notes.md index d89edb0..b289642 100644 --- a/docs/at-notes.md +++ b/docs/at-notes.md @@ -71,7 +71,7 @@ Use TID (timestamp-based identifiers) per Lexicon spec. Format: `at:////` -Example: `at://did:plc:abc123/app.malfestio.deck/3k5abc123` +Example: `at://did:plc:abc123/org.stormlightlabs.malfestio.deck/3k5abc123` ## Firehose / Jetstream diff --git a/docs/data-model-mapping.md b/docs/data-model-mapping.md index b794a92..b290fff 100644 --- a/docs/data-model-mapping.md +++ b/docs/data-model-mapping.md @@ -13,22 +13,22 @@ This document maps the public AT Protocol Lexicon records to our internal SQL da ## Mapping Table -| Public Lexicon | Internal DB Table(s) | Notes | -| :----------------------------- | :------------------- | :------------------------------------------------------------- | -| `app.malfestio.deck` | `decks` | Public metadata. | -| `app.malfestio.card` | `cards` | Content. | -| `app.malfestio.note` | `notes` | Standalone notes. | -| `app.malfestio.source.*` | `sources` | Metadata for articles/lectures. | -| `app.malfestio.collection` | `collections` | | -| `app.malfestio.thread.comment` | `comments` | | -| _(None)_ | `reviews` | **Private**. Logs of every review event. | -| _(None)_ | `study_progress` | **Private**. Current SRS state for a card (box/interval/ease). | -| _(None)_ | `user_settings` | **Private**. Daily goals, UI references. | -| _(None)_ | `drafts` | **Private**. Content being authored before publishing. | +| Public Lexicon | Internal DB Table(s) | Notes | +| :-------------------------------------------- | :------------------- | :------------------------------------------------------------- | +| `org.stormlightlabs.malfestio.deck` | `decks` | Public metadata. | +| `org.stormlightlabs.malfestio.card` | `cards` | Content. | +| `org.stormlightlabs.malfestio.note` | `notes` | Standalone notes. | +| `org.stormlightlabs.malfestio.source.*` | `sources` | Metadata for articles/lectures. | +| `org.stormlightlabs.malfestio.collection` | `collections` | | +| `org.stormlightlabs.malfestio.thread.comment` | `comments` | | +| _(None)_ | `reviews` | **Private**. Logs of every review event. | +| _(None)_ | `study_progress` | **Private**. Current SRS state for a card (box/interval/ease). | +| _(None)_ | `user_settings` | **Private**. Daily goals, UI references. | +| _(None)_ | `drafts` | **Private**. Content being authored before publishing. | ## Sync Strategy - **Publishing**: - Write to `drafts` -> User clicks "Publish" -> Sign record -> Push to PDS -> Move `drafts` content to `decks`/`cards` tables (or mark as synced). + Write to `drafts` -> User clicks "Publish" -> Sign record -> Push to PDS -> Move `drafts` content to `decks`/`cards` tables (or mark as synced). - **Consuming**: - Pull from PDS (firehose or direct sync) -> Validate signature -> Upsert into local tables. + Pull from PDS (firehose or direct sync) -> Validate signature -> Upsert into local tables. diff --git a/docs/information-architecture.md b/docs/information-architecture.md index 73ea973..1114522 100644 --- a/docs/information-architecture.md +++ b/docs/information-architecture.md @@ -44,16 +44,16 @@ This document defines the application structure, navigation, and data model mapp Mapping screens to underlying data entities (Lexicon Records + Private State). -| Screen / Component | Primary Data Entity | Secondary Entities | Private/Public | -| :----------------- | :----------------------------- | :---------------------------------------- | :---------------------------- | -| **Deck Overview** | `app.malfestio.deck` | `app.malfestio.card` (refs), User Profile | **Public** | -| **Study Session** | N/A (Ephemeral) | `app.malfestio.card`, Private Review Log | **Private** | -| **Card View** | `app.malfestio.card` | `app.malfestio.note`, Media Blobs | **Public** | -| **Editor** | Draft State (Local) | Source (`article`), `note` | **Private (Draft) -> Public** | -| **Source View** | `app.malfestio.source.article` | `app.malfestio.note` (linked) | **Public** | -| **Note View** | `app.malfestio.note` | Backlinks (`card`/`deck`) | **Public** | -| **Library** | `app.malfestio.collection` | Bookmarks, User Prefs | **Mixed** | -| **Comments** | `app.malfestio.thread.comment` | User Profile | **Public** | +| Screen / Component | Primary Data Entity | Secondary Entities | Private/Public | +| :----------------- | :-------------------------------------------- | :------------------------------------------------------- | :---------------------------- | +| **Deck Overview** | `org.stormlightlabs.malfestio.deck` | `org.stormlightlabs.malfestio.card` (refs), User Profile | **Public** | +| **Study Session** | N/A (Ephemeral) | `org.stormlightlabs.malfestio.card`, Private Review Log | **Private** | +| **Card View** | `org.stormlightlabs.malfestio.card` | `org.stormlightlabs.malfestio.note`, Media Blobs | **Public** | +| **Editor** | Draft State (Local) | Source (`article`), `note` | **Private (Draft) -> Public** | +| **Source View** | `org.stormlightlabs.malfestio.source.article` | `org.stormlightlabs.malfestio.note` (linked) | **Public** | +| **Note View** | `org.stormlightlabs.malfestio.note` | Backlinks (`card`/`deck`) | **Public** | +| **Library** | `org.stormlightlabs.malfestio.collection` | Bookmarks, User Prefs | **Mixed** | +| **Comments** | `org.stormlightlabs.malfestio.thread.comment` | User Profile | **Public** | ## URL Structure diff --git a/docs/share-vs-private-rules.md b/docs/share-vs-private-rules.md index 84271da..a931cde 100644 --- a/docs/share-vs-private-rules.md +++ b/docs/share-vs-private-rules.md @@ -15,13 +15,13 @@ This distinction is critical for the application's architecture and user privacy These entities are visible to anyone with access to the PDS (essentially public). -- Deck (`app.malfestio.deck`): The collection of cards/notes. -- Card (`app.malfestio.card`): The flashcard content (Front/Back). -- Note (`app.malfestio.note`): The source knowledge note. -- Article (`app.malfestio.source.article`): Metadata/snapshot of an external article. -- Lecture (`app.malfestio.source.lecture`): Metadata/outline of an external video/audio. -- Collection (`app.malfestio.collection`): Curated lists of decks. -- Comment (`app.malfestio.thread.comment`): Public discussion. +- Deck (`org.stormlightlabs.malfestio.deck`): The collection of cards/notes. +- Card (`org.stormlightlabs.malfestio.card`): The flashcard content (Front/Back). +- Note (`org.stormlightlabs.malfestio.note`): The source knowledge note. +- Article (`org.stormlightlabs.malfestio.source.article`): Metadata/snapshot of an external article. +- Lecture (`org.stormlightlabs.malfestio.source.lecture`): Metadata/outline of an external video/audio. +- Collection (`org.stormlightlabs.malfestio.collection`): Curated lists of decks. +- Comment (`org.stormlightlabs.malfestio.thread.comment`): Public discussion. > **Rule**: If a user puts sensitive information in a Card, they must be warned that > publishing the Deck makes it public. diff --git a/docs/todo.md b/docs/todo.md index 930008a..2e790f1 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -131,7 +131,7 @@ **Indexing:** -- [ ] Subscribe to `com.atproto.sync.subscribeRepos` (or Jetstream) for `app.malfestio.*` records +- [ ] Subscribe to `com.atproto.sync.subscribeRepos` (or Jetstream) for `org.stormlightlabs.malfestio.*` records - [ ] Index posts with compound cursor (timestamp::CID) for deterministic pagination - [ ] Garbage collect indexed data older than 48 hours (except pinned content) diff --git a/lexicons/README.md b/lexicons/README.md index 5843a58..24f8330 100644 --- a/lexicons/README.md +++ b/lexicons/README.md @@ -11,13 +11,13 @@ This directory contains the Lexicon definitions for the malfestio's public recor ### Namespace + NSID conventions -- `app.malfestio.note` -- `app.malfestio.card` -- `app.malfestio.deck` -- `app.malfestio.source.article` -- `app.malfestio.source.lecture` -- `app.malfestio.collection` -- `app.malfestio.thread.comment` +- `org.stormlightlabs.malfestio.note` +- `org.stormlightlabs.malfestio.card` +- `org.stormlightlabs.malfestio.deck` +- `org.stormlightlabs.malfestio.source.article` +- `org.stormlightlabs.malfestio.source.lecture` +- `org.stormlightlabs.malfestio.collection` +- `org.stormlightlabs.malfestio.thread.comment` ### Lexicon basics @@ -38,4 +38,4 @@ This directory contains the Lexicon definitions for the malfestio's public recor 2. **No Renaming**: Do not rename fields. If a semantic change is needed, add a new field and deprecate the old one. 3. **No Type Changes**: Once published, a field's type is fixed. -4. **Version by Copying**: If a breaking change is absolutely required, create a new Lexicon with a new major version or a new name (e.g., `app.malfestio.noteV2`). +4. **Version by Copying**: If a breaking change is absolutely required, create a new Lexicon with a new major version or a new name (e.g., `org.stormlightlabs.malfestio.noteV2`). diff --git a/lexicons/app/malfestio/card.json b/lexicons/org/stormlightlabs/malfestio/card.json similarity index 97% rename from lexicons/app/malfestio/card.json rename to lexicons/org/stormlightlabs/malfestio/card.json index baa53ce..912457c 100644 --- a/lexicons/app/malfestio/card.json +++ b/lexicons/org/stormlightlabs/malfestio/card.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.card", + "id": "org.stormlightlabs.malfestio.card", "defs": { "main": { "type": "record", diff --git a/lexicons/app/malfestio/collection.json b/lexicons/org/stormlightlabs/malfestio/collection.json similarity index 95% rename from lexicons/app/malfestio/collection.json rename to lexicons/org/stormlightlabs/malfestio/collection.json index 9cf52a2..5d25537 100644 --- a/lexicons/app/malfestio/collection.json +++ b/lexicons/org/stormlightlabs/malfestio/collection.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.collection", + "id": "org.stormlightlabs.malfestio.collection", "defs": { "main": { "type": "record", diff --git a/lexicons/app/malfestio/deck.json b/lexicons/org/stormlightlabs/malfestio/deck.json similarity index 96% rename from lexicons/app/malfestio/deck.json rename to lexicons/org/stormlightlabs/malfestio/deck.json index aeb82d0..0c764d9 100644 --- a/lexicons/app/malfestio/deck.json +++ b/lexicons/org/stormlightlabs/malfestio/deck.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.deck", + "id": "org.stormlightlabs.malfestio.deck", "defs": { "main": { "type": "record", diff --git a/lexicons/app/malfestio/note.json b/lexicons/org/stormlightlabs/malfestio/note.json similarity index 97% rename from lexicons/app/malfestio/note.json rename to lexicons/org/stormlightlabs/malfestio/note.json index 4f61f22..4ca48a0 100644 --- a/lexicons/app/malfestio/note.json +++ b/lexicons/org/stormlightlabs/malfestio/note.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.note", + "id": "org.stormlightlabs.malfestio.note", "defs": { "main": { "type": "record", diff --git a/lexicons/app/malfestio/source/article.json b/lexicons/org/stormlightlabs/malfestio/source/article.json similarity index 96% rename from lexicons/app/malfestio/source/article.json rename to lexicons/org/stormlightlabs/malfestio/source/article.json index b5c90a5..28f6690 100644 --- a/lexicons/app/malfestio/source/article.json +++ b/lexicons/org/stormlightlabs/malfestio/source/article.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.source.article", + "id": "org.stormlightlabs.malfestio.source.article", "defs": { "main": { "type": "record", diff --git a/lexicons/app/malfestio/source/lecture.json b/lexicons/org/stormlightlabs/malfestio/source/lecture.json similarity index 96% rename from lexicons/app/malfestio/source/lecture.json rename to lexicons/org/stormlightlabs/malfestio/source/lecture.json index aeea89e..ac448ea 100644 --- a/lexicons/app/malfestio/source/lecture.json +++ b/lexicons/org/stormlightlabs/malfestio/source/lecture.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.source.lecture", + "id": "org.stormlightlabs.malfestio.source.lecture", "defs": { "main": { "type": "record", diff --git a/lexicons/app/malfestio/thread/comment.json b/lexicons/org/stormlightlabs/malfestio/thread/comment.json similarity index 92% rename from lexicons/app/malfestio/thread/comment.json rename to lexicons/org/stormlightlabs/malfestio/thread/comment.json index acf9fa4..8e59c71 100644 --- a/lexicons/app/malfestio/thread/comment.json +++ b/lexicons/org/stormlightlabs/malfestio/thread/comment.json @@ -1,6 +1,6 @@ { "lexicon": 1, - "id": "app.malfestio.thread.comment", + "id": "org.stormlightlabs.malfestio.thread.comment", "defs": { "main": { "type": "record", diff --git a/migrations/012_2026_01_02_add_card_type.sql b/migrations/012_2026_01_02_add_card_type.sql new file mode 100644 index 0000000..9c96a7c --- /dev/null +++ b/migrations/012_2026_01_02_add_card_type.sql @@ -0,0 +1,5 @@ +-- Migration: Add card_type column to cards table +-- Date: 2026-01-02 +-- Issue: card_type was not being persisted, always returning 'basic' + +ALTER TABLE cards ADD COLUMN IF NOT EXISTS card_type TEXT DEFAULT 'basic'; diff --git a/web/src/components/TutorialOverlay.tsx b/web/src/components/TutorialOverlay.tsx index 7511ed3..5c0d2e7 100644 --- a/web/src/components/TutorialOverlay.tsx +++ b/web/src/components/TutorialOverlay.tsx @@ -11,12 +11,13 @@ const getTooltipPosition = (target: Position, placement: "top" | "bottom" | "lef const tooltipWidth = 320; switch (placement) { - case "top": + case "top": { + const tooltipHeight = 240; return { - top: target.top - padding - 8, + top: target.top - padding - 16 - tooltipHeight, left: target.left + target.width / 2 - tooltipWidth / 2, - transform: "translateY(-100%)", }; + } case "bottom": return { top: target.top + target.height + padding, left: target.left + target.width / 2 - tooltipWidth / 2 }; case "left": @@ -94,7 +95,7 @@ export const TutorialOverlay: Component = () => { exit={{ opacity: 0 }} transition={{ duration: 0.2 }} class="fixed inset-0 z-50 pointer-events-none"> - + {(pos) => ( <> { @@ -120,22 +121,25 @@ export const TutorialOverlay: Component = () => { onClick={() => tutorial.skipTutorial()} /> -
-
{

Use ← → arrow keys or Esc to skip

-
+ )} diff --git a/web/src/components/tests/DeckPreview.test.tsx b/web/src/components/tests/DeckPreview.test.tsx index 2a00566..e78b9d0 100644 --- a/web/src/components/tests/DeckPreview.test.tsx +++ b/web/src/components/tests/DeckPreview.test.tsx @@ -9,7 +9,7 @@ vi.mock("$lib/api", () => ({ api: { getRemoteDeck: vi.fn() } })); vi.mock( "@solidjs/router", () => ({ - useSearchParams: () => [{ uri: "at://did:plc:test/app.malfestio.deck/123" }], + useSearchParams: () => [{ uri: "at://did:plc:test/org.stormlightlabs.malfestio.deck/123" }], useNavigate: () => vi.fn(), A: (props: { href: string; children: JSX.Element }) => {props.children}, }), @@ -29,7 +29,7 @@ describe("DeckPreview", () => { ok: true, json: async () => ({ deck: { - id: "at://did:plc:test/app.malfestio.deck/123", + id: "at://did:plc:test/org.stormlightlabs.malfestio.deck/123", owner_did: "did:plc:test", title: "Remote Deck", description: "A test deck", diff --git a/web/src/components/tests/Library.test.tsx b/web/src/components/tests/Library.test.tsx index bbb957a..6d52ed6 100644 --- a/web/src/components/tests/Library.test.tsx +++ b/web/src/components/tests/Library.test.tsx @@ -32,7 +32,7 @@ describe("Library page", () => { title: "Federated Deck", description: "From another server", tags: ["remote"], - at_uri: "at://did:plc:other/app.malfestio.deck/deck1", + at_uri: "at://did:plc:other/org.stormlightlabs.malfestio.deck/deck1", }, rank: 1, source: "remote", -- 2.51.2