Skip to content

Support Profile Live Status, Data Layer#1049

Open
joelmuraguri wants to merge 9 commits intomainfrom
joel/profile-status-data-layer
Open

Support Profile Live Status, Data Layer#1049
joelmuraguri wants to merge 9 commits intomainfrom
joel/profile-status-data-layer

Conversation

@joelmuraguri
Copy link
Collaborator

No description provided.

@joelmuraguri joelmuraguri requested a review from tunjid February 27, 2026 21:47
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive support for a 'live status' feature within user profiles, focusing on the underlying data layer. It establishes new data models to represent profile status, integrates these models into the application's local persistence layer, and provides the necessary repository functions to update and manage a user's live status, including going live with an external stream URL or ending a live session. The changes ensure that profile status information can be effectively stored, retrieved, and synchronized across the application.

Highlights

  • Profile Live Status Model: Introduced a new ProfileStatus data model within the Profile class, including properties for status value, embed information, expiration, and active/disabled flags. A computed isLive property was also added.
  • Data Layer Support for Status Updates: Implemented the updateStatus function in ProfileRepository to handle GoLive and EndLive operations, allowing profiles to set or clear their live status. This involves interacting with the network API to create or delete status records.
  • Database Integration for Profile Status: Added a new profile_statuses table to the Room database schema, along with a corresponding ProfileStatusEntity. The ProfileDao was extended with upsertStatus and deleteStatus methods to persist and manage profile live status locally.
  • Writable Queue Integration: Extended the Writable interface and WriteQueue to support StatusUpdate operations, ensuring that profile status changes are processed through the application's write queue mechanism.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • data/core/src/commonMain/kotlin/com/tunjid/heron/data/network/models/ProfileConversions.kt
    • Added imports for StatusView and StatusViewEmbedUnion.
    • Included a status field in the conversion of ProfileViewBasic and ProfileView to Profile.
    • Implemented a new StatusView.profileStatus() extension function to convert network status views into the internal Profile.ProfileStatus model.
  • data/core/src/commonMain/kotlin/com/tunjid/heron/data/repository/ProfileRepository.kt
    • Added imports for Status, StatusEmbedUnion, External, ExternalExternal, and LexiconUri.
    • Imported Duration.Companion.minutes for time calculations.
    • Introduced updateStatus to the ProfileRepository interface.
    • Implemented updateStatus in OfflineProfileRepository to handle GoLive (creating a new status record via putRecord) and EndLive (deleting a status record via deleteRecord) operations, with corresponding local database updates.
  • data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/Collections.kt
    • Added ProfileStatus constant for the app.bsky.actor.status collection.
  • data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/writequeue/Writable.kt
    • Added a new StatusUpdate sealed class member to the Writable interface, which delegates to profileRepository.updateStatus.
  • data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/writequeue/WriteQueue.kt
    • Included Writable.StatusUpdate in the writeTimeout() function, assigning it a BasicWriteTimeout.
  • data/database/schemas/com.tunjid.heron.data.database.AppDatabase/34.json
    • Updated the database identityHash.
    • Added a new profile_statuses table schema with fields for profileId, statusValue, embedUri, embedTitle, embedDescription, embedThumb, expiresAt, isActive, isDisabled, and a foreign key constraint to the profiles table.
  • data/database/src/commonMain/kotlin/com/tunjid/heron/data/database/AppDatabase.kt
    • Imported ProfileStatusEntity.
    • Added ProfileStatusEntity to the list of entities managed by AppDatabase.
  • data/database/src/commonMain/kotlin/com/tunjid/heron/data/database/daos/ProfileDao.kt
    • Imported ProfileId and ProfileStatusEntity.
    • Added upsertStatus and deleteStatus suspend functions to manage ProfileStatusEntity records in the database.
  • data/database/src/commonMain/kotlin/com/tunjid/heron/data/database/entities/ProfileEntity.kt
    • Modified ProfileEntity.asExternalModel() to include a status field, initialized to null.
    • Added a @Relation to PopulatedProfileEntity to fetch the associated ProfileStatusEntity.
    • Updated PopulatedProfileEntity.asExternalModel() to map the statusEntity to the external Profile.ProfileStatus model.
  • data/database/src/commonMain/kotlin/com/tunjid/heron/data/database/entities/ProfileStatusEntity.kt
    • Added a new file defining ProfileStatusEntity for Room database persistence.
    • Provided conversion functions asExternalModel() to convert ProfileStatusEntity to Profile.ProfileStatus and asEntity() for the reverse.
  • data/models/src/commonMain/kotlin/com/tunjid/heron/data/core/models/Profile.kt
    • Added a nullable status: ProfileStatus? field to the Profile data class.
    • Defined ProfileStatus as a nested data class within Profile, including uri, status, embed, expiresAt, isActive, isDisabled, and an isLive computed property.
    • Defined Embed as a nested data class within ProfileStatus for external content details.
    • Introduced StatusUpdate as a sealed class within Profile, with GoLive and EndLive subclasses to represent different types of status updates.
    • Updated stubProfile to include status = null.
  • ui/timeline/src/commonMain/composeResources/values/strings.xml
    • Added a new string resource writable_status_update with the value "profile status update".
  • ui/timeline/src/commonMain/kotlin/com/tunjid/heron/timeline/utilities/WriteQueueStatusMemos.kt
    • Imported the new writable_status_update string resource.
    • Added a case for Writable.StatusUpdate in writeStatusMessage to display a user-friendly message for status updates.
Activity
  • No specific activity (comments, reviews, or progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for profile live status across the data layer. The changes are well-structured, including updates to the domain models, repository, database schema, and write queue. The implementation is comprehensive and follows existing patterns in the codebase. I have one suggestion to improve the feature by avoiding hardcoded empty strings for the live stream's title and description, which would provide a richer user experience.

Comment on lines +550 to +554
external = ExternalExternal(
uri = LexiconUri(update.streamUrl),
title = "",
description = "",
),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The title and description for the live status are hardcoded as empty strings. This is also repeated in the toOutcome block on lines 567-568.

This is a missed opportunity to provide more context about the live stream. Consider enhancing the Profile.StatusUpdate.GoLive model to accept an optional title and description. If they aren't provided, you could attempt to fetch this metadata from the streamUrl (e.g., by parsing OpenGraph tags from the HTML at the URL). This would make the feature more robust and provide a better user experience.

"formatVersion": 1,
"database": {
"version": 34,
"identityHash": "1e975be4633a2c929f918f6201d3bdf4",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the DB identity hash changes, it means you're missing a migration. The identity has hash for a DB version shouldn't change.

import com.tunjid.heron.data.core.types.ProfileId
import kotlin.time.Instant

@Entity(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think creating a ProfileStatusEntity is needed. A profile can only have one status, and that status is the one with the self record key. Each time a profile goes live, its always updating its self status.

That is, a profile status is a 1:1 record. The status should be a nullable embedded record in the ProfileEntity

)

@Serializable
data class ProfileStatus(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is most likely going to be an embedded model in ProfileEntity, we should make it a flat data class.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e:

    data class ProfileStatus(
        val uri: String? = null,
        val status: String,
        val uri: String,
        val title: String,
        val description: String,
        val thumb: ImageUri? = null,
        val expiresAt: Instant? = null,
        val isActive: Boolean? = null,
        val isDisabled: Boolean? = null,
    )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants