<freeStyleBuild _class='hudson.model.FreeStyleBuild'><action _class='hudson.model.CauseAction'><cause _class='hudson.triggers.TimerTrigger$TimerTriggerCause'><shortDescription>Started by timer</shortDescription></cause></action><action></action><action _class='hudson.plugins.git.util.BuildData'><buildsByBranchName><refsremotesoriginmain _class='hudson.plugins.git.util.Build'><buildNumber>45</buildNumber><marked><SHA1>beec082677ecfe343236c083f1545d158453e63f</SHA1><branch><SHA1>beec082677ecfe343236c083f1545d158453e63f</SHA1><name>refs/remotes/origin/main</name></branch></marked><revision><SHA1>beec082677ecfe343236c083f1545d158453e63f</SHA1><branch><SHA1>beec082677ecfe343236c083f1545d158453e63f</SHA1><name>refs/remotes/origin/main</name></branch></revision></refsremotesoriginmain><refsremotesorigindev-xapi-ipc _class='hudson.plugins.git.util.Build'><buildNumber>9</buildNumber><marked><SHA1>35548db75de85c0441a83620284c3f99155699c1</SHA1><branch><SHA1>35548db75de85c0441a83620284c3f99155699c1</SHA1><name>refs/remotes/origin/dev-xapi-ipc</name></branch></marked><revision><SHA1>35548db75de85c0441a83620284c3f99155699c1</SHA1><branch><SHA1>35548db75de85c0441a83620284c3f99155699c1</SHA1><name>refs/remotes/origin/dev-xapi-ipc</name></branch></revision></refsremotesorigindev-xapi-ipc></buildsByBranchName><lastBuiltRevision><SHA1>beec082677ecfe343236c083f1545d158453e63f</SHA1><branch><SHA1>beec082677ecfe343236c083f1545d158453e63f</SHA1><name>refs/remotes/origin/main</name></branch></lastBuiltRevision><remoteUrl>https://github.com/UstadMobile/Respect.git</remoteUrl><scmName></scmName></action><action></action><action></action><action></action><action></action><action></action><action _class='org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction'></action><artifact><displayPath>respect-cli-1.0.34a.zip</displayPath><fileName>respect-cli-1.0.34a.zip</fileName><relativePath>respect-cli/build/distributions/respect-cli-1.0.34a.zip</relativePath></artifact><artifact><displayPath>respect-server-1.0.34a.zip</displayPath><fileName>respect-server-1.0.34a.zip</fileName><relativePath>respect-server/build/distributions/respect-server-1.0.34a.zip</relativePath></artifact><artifact><displayPath>respect-server-shadow-1.0.34a.zip</displayPath><fileName>respect-server-shadow-1.0.34a.zip</fileName><relativePath>respect-server/build/distributions/respect-server-shadow-1.0.34a.zip</relativePath></artifact><building>false</building><displayName>#45</displayName><duration>156065</duration><estimatedDuration>159136</estimatedDuration><fullDisplayName>RESPECT-Primary-MavenPublish #45</fullDisplayName><id>45</id><inProgress>false</inProgress><keepLog>false</keepLog><number>45</number><queueId>10861</queueId><result>SUCCESS</result><timestamp>1785481320420</timestamp><url>https://devserver3.ustadmobile.com/jenkins/job/RESPECT-Primary-MavenPublish/45/</url><builtOn></builtOn><changeSet _class='hudson.plugins.git.GitChangeSetList'><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>README.md</affectedPath><commitId>97ac20242d7390216f788048a1b7854592ce390c</commitId><timestamp>1785405360000</timestamp><author><absoluteUrl>https://devserver3.ustadmobile.com/jenkins/user/noreply</absoluteUrl><fullName>noreply</fullName></author><authorEmail>noreply@github.com</authorEmail><comment>Update README.md

Update README.md to specify using the latest stable channel version of Android Studio
</comment><date>2026-07-30 13:56:00 +0400</date><id>97ac20242d7390216f788048a1b7854592ce390c</id><msg>Update README.md</msg><path><editType>edit</editType><file>README.md</file></path></item><item _class='hudson.plugins.git.GitChangeSet'><affectedPath>respect-lib-shared/src/commonMain/composeResources/values/strings.xml</affectedPath><affectedPath>app-android/src/main/kotlin/world/respect/AppKoinModule.kt</affectedPath><affectedPath>respect-datalayer-db/schemas/world.respect.datalayer.db.RespectAppDatabase/6.json</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/apps/detail/AppsDetailViewModel.kt</affectedPath><affectedPath>.maestro/flows/002_001_browse_lessons_test.yaml</affectedPath><affectedPath>.maestro/flows/001_002_add_user_direct_test.yaml</affectedPath><affectedPath>.maestro/flows/003_admin_user_assigns_assignment_to_a_class_test.yaml</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/apps/launcher/AppLauncherViewModel.kt</affectedPath><affectedPath>respect-app-compose/src/androidMain/kotlin/world/respect/shared/domain/license/GetLicenseLabelUseCaseAndroid.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/geticonforxapiactivity/GetPublicationForXapiActivityUseCase.kt</affectedPath><affectedPath>.maestro/flows/002_002_browse_demo_app_test.yaml</affectedPath><affectedPath>respect-lib-xapi-core/src/commonMain/kotlin/world/respect/lib/xapi/model/XapiVerb.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/navigation/AppRoutes.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/util/CommonSortOptions.kt</affectedPath><affectedPath>respect-lib-shared/src/androidMain/kotlin/world/respect/shared/domain/launchapp/LaunchAppUseCaseAndroid.kt</affectedPath><affectedPath>respect-server/src/main/kotlin/world/respect/server/demoapp/DemoLaunchableAppManifestRoute.kt</affectedPath><affectedPath>respect-datalayer-db/schemas/world.respect.datalayer.db.RespectAppDatabase/5.json</affectedPath><affectedPath>.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml</affectedPath><affectedPath>respect-server/src/main/resources/http/respect-ds/case_valid/js/xapi_statement_maker.js</affectedPath><affectedPath>respect-lib-shared/src/commonMain/composeResources/drawable/no_bookmark.xml</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/app/AppNavHost.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/bookmark/AddBookmarkUseCase.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/license/GetLicenseLabelUseCase.kt</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/bookmark/BookmarkListScreen.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/learningunit/detail/LearningUnitDetailViewModel.kt</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/learningunit/list/LearningUnitListScreen.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/bookmark/RemoveBookmarkUseCase.kt</affectedPath><affectedPath>respect-lib-xapi-core/src/commonMain/kotlin/world/respect/lib/xapi/OpenEelXapiConstants.kt</affectedPath><affectedPath>respect-server/src/main/resources/http/respect-ds/case_valid/examples/statementmaker/index.html</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/learningunit/detail/LearningUnitDetailScreen.kt</affectedPath><affectedPath>.maestro/flows/001_003_login_using_school_link_test.yaml</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/app/appstate/Snack.kt</affectedPath><affectedPath>.maestro/flows/subflows/admin_add_app.yaml</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/app/App.kt</affectedPath><affectedPath>respect-app-compose/src/androidMain/kotlin/world/respect/WebViewActivity.kt</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/learningunit/list/PublicationListItem.kt</affectedPath><affectedPath>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/bookmark/BookmarkListViewModel.kt</affectedPath><affectedPath>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/home/HomeScreen.kt</affectedPath><commitId>beec082677ecfe343236c083f1545d158453e63f</commitId><timestamp>1785408254000</timestamp><author><absoluteUrl>https://devserver3.ustadmobile.com/jenkins/user/noreply</absoluteUrl><fullName>noreply</fullName></author><authorEmail>noreply@github.com</authorEmail><comment>Dev bookmark xapi (#272)

* Add bookmark button to lesson details

* Add bookmark functionality for learning units

Key changes include:
- Updating the `OpdsDataSource` interface and its implementations (`OpdsDataSourceRepository`, `OpdsDataSourceDb`) to handle observing and setting bookmark status.
- Adding a `BookmarkEntity` and `BookmarkDao` to the database schema to persist bookmark state.
- Implementing the bookmark logic in the `LearningUnitDetailViewModel`, which now observes and updates the bookmark status.
- The bookmark button in `LearningUnitDetailScreen` now dynamically changes its icon based on whether the unit is bookmarked.

* feat: Add bookmark data layer

Introduced the data layer components required for managing publication bookmarks.

This includes:
- A `BookmarkEntity` to store bookmark status and timestamp.
- A `BookmarkDao` with functions to insert/update bookmarks, observe a single bookmark's status, and retrieve all bookmarked publications.
- An implementation in `OpdsDataSourceDb` to get a flow of bookmarked `OpdsPublication` objects.
- An update to `ReadiumLinkEntityDao` to find all links associated with a publication UID.

* feat: Implement fetching of bookmarked publications

This commit introduces the functionality to retrieve a list of all bookmarked publications from the local database.

Key changes:

-   Added `getBookmarkedPublications()` to the `OpdsDataSource` interface.
-   Implemented the new function in `OpdsDataSourceRepository` to delegate the call to the local data source.
-   In `OpdsDataSourceDb`, the implementation now fetches bookmarked publication entities from `BookmarkDao` and maps them to `OpdsPublication` models.
-   Updated the `OpdsDataSourceHttp` stub to include the new interface method.

* feat: Store title and timestamp for bookmarks

This change enhances the bookmarking functionality by storing the title of the bookmarked item and implicitly tracking when it was last updated.

Key changes include:
- Updating the `setBookmarkStatus` function across the `OpdsDataSource` interface and its implementations (`OpdsDataSourceDb`, `OpdsDataSourceRepository`, `OpdsDataSourceHttp`) to accept a `title` parameter.
- Modifying the `BookmarkDao` to no longer retrieve `OpdsPublicationEntity` objects directly. Instead, a new `observeAllBookmarks` function returns a flow of `BookmarkEntity` objects, ordered by their update timestamp.
- The `LearningUnitDetailViewModel` now passes the lesson title when setting the bookmark status.
- The `OpdsDataSourceDb` was updated to implement these DAO changes and now provides a `getAllBookmarks` function.

* Implement fetching of all bookmarks
This commit introduces the functionality to retrieve a list of all bookmarks.

* Display app name and icon on learning unit detail screen

* Store subtitle and app icon for bookmarks

* Store subtitle and app icon for bookmarks

* Improve code formatting in OpdsDataSourceDb

* Improve code formatting in OpdsDataSourceDb

* Implement bookmark list screen

* Implement bookmark list screen

* Implement bookmark list screen

* Implement bookmark list screen

* Implement bookmark list screen

* Implement bookmark list screen

* Refactor bookmarking logic to toggle status

This commit refactors the bookmarking functionality. Instead of explicitly passing a boolean to set the bookmark status, the `setBookmarkStatus` function now toggles the state. If a bookmark exists, it's removed; otherwise, a new one is created.

This change simplifies the bookmarking logic across the data layers and the view model. Additionally, the bookmark list screen now allows for the removal of bookmarks.

* Refactor bookmarking logic to toggle status

This commit refactors the bookmarking functionality. Instead of explicitly passing a boolean to set the bookmark status, the `setBookmarkStatus` function now toggles the state. If a bookmark exists, it's removed; otherwise, a new one is created.

This change simplifies the bookmarking logic across the data layers and the view model. Additionally, the bookmark list screen now allows for the removal of bookmarks.

* Delete respect-datalayer-db/schemas/world.respect.datalayer.db.RespectAppDatabase/2.json

* Refactor bookmarking logic to toggle status

This commit refactors the bookmarking functionality. Instead of explicitly passing a boolean to set the bookmark status, the `setBookmarkStatus` function now toggles the state. If a bookmark exists, it's removed; otherwise, a new one is created.

This change simplifies the bookmarking logic across the data layers and the view model. Additionally, the bookmark list screen now allows for the removal of bookmarks.

* Refactor bookmarking logic to toggle status

* Refactor: Enhance bookmark data and enable navigation

* Seperation of bookmark implementation

* Seperation of bookmark implementation

* Update bookmark data model to include learning unit URL

* Update bookmark

* Move bookmarking logic from respect app data source to school data source

* Update bookmark logic to use enum to delete

* Rename bookmark observation methods to getBookmarkStatus and getAllBookmarks

* Rename bookmark observation methods to getBookmarkStatus and getAllBookmarks

* Refactor bookmarking logic to use Bookmark model and toggle status

* Refactor bookmarking logic to use Bookmark model and toggle status

* Refactor bookmarking logic to use Bookmark model and toggle status

* Refactor bookmarking logic to use Bookmark model and toggle status

* Rename Bookmark field learningUnitUrl to learningUnitManifestUrl

This commit renames the `learningUnitUrl` property in the `Bookmark` data class to `learningUnitManifestUrl` for better clarity and consistency with other parts of the codebase.

The changes include:
- Updating the `Bookmark` model definition.
- Updating the `BookmarkAdapter` mapping logic to reflect the rename.
- Adjusting usages in `LearningUnitDetailViewModel` and `BookmarkListViewModel`.
- Updating the database access logic in `BookmarkDataSourceDb`.
- Cleaning up unused imports.

* Rename Bookmark field learningUnitUrl to learningUnitManifestUrl

* Added playlist test

* Move bookmark-related database components to the school package

* Move bookmark-related database components to the school package

* Added bookmark test

* Add user identification to bookmark database components

* Add user identification to bookmark database components

* Add user identification to bookmark database components

* Update bookmark storage logic

* Implement bookmark toggling and update database components

* Refactor bookmark data layer to use unique identifiers and timestamps

* Refactor bookmark data layer to use composite primary keys and remove UID generation logic

* Refactor bookmark data layer to use composite primary keys and remove UID generation logic

* Clean up code and refactor bookmark icon logic

* Implement bookmark data layer including HTTP, DB, and Repository components

* Update Bookmark model and data layer to support titles, subtitles, and images.

- Add `title`, `subtitle`, and `imageUrl` properties to the `Bookmark` model.
- Implement `BookmarkEntities` and `PublicationWithDetails` in the DB layer to handle relational data for bookmarks and OPDS publications.
- Update `BookmarkDao` and `BookmarkDataSourceDb` to return bookmarks with their associated publication details.
- Refactor `BookmarkListScreen` to display bookmark images and text content.
- Add navigation logic to `AppLauncherViewModel` for navigating to the bookmark list.
- Minor clean up and documentation updates in OPDS and Bookmark entities.

* Remove title, subtitle, and image fields from Bookmark model and DAO logic

* Add localized title support to bookmarks and update database relations

* Refactor LearningUnitDetailViewModel and clean up unused imports and whitespace.

* Update Bookmark model and data layer to include subtitles and improve app detail handling in LearningUnitDetailScreen.

* Remove properties

* Update BookmarkListViewModel to use LoadingUiState and clean up imports

* Update BookmarkListViewModel to use LoadingUiState and clean up imports

* Update BookmarkListViewModel to use LoadingUiState and clean up imports

* Update BookmarkListViewModel to use LoadingUiState and clean up imports

* Clean up formatting in BookmarkDao

* Clean up formatting in BookmarkAdapter.kt

* Clean up

* Clean up

* Clean up

* Clean up LearningUnitDetailViewModel constructor and improve code formatting

* Add image URL support to Bookmark model and UI components

* Add BookmarkEntity to database schema and implement navigation to bookmark list from app launcher.

* Add BookmarkEntity to database schema and implement navigation to bookmark list from app launcher.

* Add BookmarkEntity to database schema and implement navigation to bookmark list from app launcher.

* Added lesson002 and updated test

* Implement bookmark navigation and fix data synchronization in BookmarkListViewModel

* Update bookmark implementation to include application manifest URLs and app metadata.

* commented bookmark code for playlist screen

* commented bookmark code for playlist screen

* Update bookmark implementation to include application manifest URLs and app metadata.

* Update bookmark data layer, database entities, and cleanup ViewModel logic

* Rename findBookmarks to findBookmarksWithMissingPublication and update loading logic in BookmarkListViewModel

* Implement getBookmarkLastModified and findByUidList in BookmarkDao and BookmarkDataSourceDb

* Register Bookmark components in RespectSchoolDatabase and update OPDS package imports

* Register Bookmark components in RespectSchoolDatabase and update OPDS package imports

* Add language, grade, and type fields to Bookmark model and display them in BookmarkListScreen

* Update navigation labels to "Home" and integrate BookmarkListScreen into HomeScreen

- Rename "Apps" navigation label to "Home" across `App.kt`, `AppLauncherViewModel`, and `BookmarkListViewModel`.
- Update `HomeScreen` to include a new "Bookmarks" tab alongside the existing "Apps" tab.
- Refactor `BookmarkListScreen` UI: remove redundant styling boxes/borders around icons and adjust icon sizing.
- Update `strings.xml` to include new "home" and "bookmarks" resources and update the bookmark empty state message.
- Update Maestro flow test to reflect UI text changes.

* Update navigation labels to "Home" and integrate BookmarkListScreen into HomeScreen

* Add NO_BOOKMARK to RespectImage and update EmptyBookmarkState UI in BookmarkListScreen

* Add NO_BOOKMARK to RespectImage and update EmptyBookmarkState UI in BookmarkListScreen

* Add NO_BOOKMARK to RespectImage and update EmptyBookmarkState UI in BookmarkListScreen

* Add NO_BOOKMARK to RespectImage and update EmptyBookmarkState UI in BookmarkListScreen

* Update UI layout and styling in BookmarkListScreen.kt

* Update UI layout and styling in BookmarkListScreen.kt

* Move no_bookmark image to shared resources and update BookmarkListScreen usage

* Implement `listAsFlow` in `BookmarkDataSource` and update `BookmarkListViewModel` to reactive flow

Instead Of using Paging Source I am using List as Flow because-App loading per item getting messy with paging

* Implement paging support for BookmarkDataSource across DB, HTTP, and Repository layers

* Remove redundant comments in BookmarkListViewModel

* Introduce `BookmarkDetails` to associate bookmarks with their corresponding application data and refactor `BookmarkListViewModel` to load these details concurrently.

* Update Maestro flows

* test - update Maestro flow for lesson browsing

* Update Maestro test flows

*   **002_browse_lessons_test.yaml**: Updated the "Bookmark" tap index from 1 to 0 and commented out several assertion and undo steps.

* Update Maestro test flows

* Update Maestro test flows

* Update BookmarkDataSource and related components to support includeDeleted parameter and fix BookmarkDao query

* Update SnackBar implementation to support actions and implement undo functionality for bookmark removal

*   Modify `App.kt` to handle `SnackbarResult` and trigger the snackbar's `onAction` callback.
*   Update `BookmarkListViewModel` to use `SnackBarDispatcher` and provide an "Undo" action when removing a bookmark.
*   Add `remove_bookmark` and `undo` string resources.

* Implement `UiText.asString()` extension and update `Snack` to support `UiText` actions

* Use default snackbar duration in App.kt

* test is failing as Snack bar appears but due to duration by the time tapOn Undo is triggered it disappears

* test: Update browse lessons Maestro flow with additional assertions

* test: update browse lessons Maestro flow

* Updated `002_browse_lessons_test.yaml` Maestro flow

* test: update Maestro browse lessons flow

* test is failing as Snack bar appears but due to duration by the time tapOn Undo is triggered it disappears

* Format code and apply style improvements across bookmark and data layer components

* Update icon URI handling in Bookmark and LearningUnit detail screens and resolve publication URLs in ViewModels

* Update snackbar message handling to support StringUiText and StringResourceUiText in App.kt

* Update snackbar message handling to support StringUiText and StringResourceUiText in App.kt

* Update bookmark query field and remote sync logic.

* Refactor data loading state and clean up bookmark-related logic.

- Move `DataLoadState`, `DataLoadParams`, and related extensions from `world.respect.datalayer` to `world.respect.lib.dataloadstate`.
- Remove `UiText.asString()` extension in favor of explicit `when` branches in the `App` composable.
- Remove `AssignmentDataSource` and related references across the data layer and server routes.
- Replace `getTitle()` with `langMapString()` for title resolution in `BookmarkListScreen` and `LearningUnitDetailScreen`.
- Fix parameter mapping in `LearningUnitDetailViewModel` to use `learningUnitManifestUrl` and update bookmark storage logic.
- Clean up unused imports and duplicate string resources.

* Add `gradle-daemon-jvm.properties` to specify Java 21 for the Gradle daemon.

* Add `gradle-daemon-jvm.properties` to specify Java 21 for the Gradle daemon.

* Add `gradle-daemon-jvm.properties` to specify Java 21 for the Gradle daemon.

* removed bookmark data source

* Refactor bookmark management to use xapi statements instead of a dedicated `BookmarkDataSource`.

- Remove `BookmarkDataSourceRepository` and its associated server-side route.
- Update `LearningUnitDetailViewModel` to fetch and store bookmark status using `xapiResource.statements` with the `ID_BOOKMARKED` verb.
- Update `BookmarkListViewModel` and `BookmarkListScreen` to display and manage bookmarks based on xapi statements and linked `OpdsPublication` data.
- Add `ID_BOOKMARKED` constant to `XapiVerb`.
- Update Maestro UI tests to reflect changes in sample data names and bookmark behavior.

* Sort bookmark statements by timestamp in `BookmarkListViewModel` and remove unused imports and test steps.

* Remove redundant newline in `002_browse_lessons_test.yaml`.

* Update Maestro flow assertions to use "Home" instead of "Apps".

* Update Maestro flow assertions to use "Home" instead of "Apps".

* Reorganize Maestro YAML files between flows and test directories.

* Update lesson visibility assertion in `002_browse_lessons_test.yaml`.

* Add `BookmarkEntity` table to `RespectSchoolDatabase` schema and move Maestro test files to the `flows` directory.

* Update school self-registration test and remove unused admin subflow.

* Update school self-registration test and remove unused admin subflow.

* Update `002_browse_lessons_test.yaml` to use `${output.TEST_APP_URL}` variable.

* Update `002_browse_lessons_test.yaml` to use `${output.TEST_APP_URL}` variable.

* Update `002_browse_lessons_test.yaml` to use `${output.TEST_APP_URL}` variable.

* Add database schema files for versions 1 through 8 of `RespectAppDatabase`.

* Add database schema files for versions 1 through 8 of `RespectAppDatabase`.

* Refine code formatting and whitespace.

* Refine code formatting and whitespace.

* Refine imports in `SchoolDataSourceDb.kt` and remove trailing whitespace in `OpdsPublicationEntityAdapter.kt`.

* Remove extraneous blank lines from documentation comments in `OpdsPublicationEntity.kt`.

* Introduce `AddBookmarkUseCase` and `RemoveBookmarkUseCase` to centralize bookmarking logic and refactor view models to use these use cases.

- Deleted legacy `Bookmark` model from `datalayer`.
- Added `AddBookmarkUseCase` and `RemoveBookmarkUseCase` in `respect-lib-shared`.
- Refactored `LearningUnitDetailViewModel` and `BookmarkListViewModel` to use the new use cases and improve error handling via snackbars.
- Updated `AppKoinModule.kt` to provide the new use cases within the account scope.
- Refined UI styles and string resources in `BookmarkListScreen`, `LearningUnitDetailScreen`, and `strings.xml`.
- Fixed typo from `accountMananger` to `accountManager` in `LearningUnitDetailViewModel`.

* Remove unused `FontWeight` import in `LearningUnitDetailScreen`.

* Include `appManifestUrl` in `LearningUnitDetail` route and xAPI bookmark statements.

- Update `LearningUnitDetail` route to include and persist `appManifestUrl`.
- Pass `appManifestUrl` through `AddBookmarkUseCase` and store it within the xAPI statement's `context.contextActivities.parent` field.
- Update `LearningUnitDetailViewModel` to fetch application data using `appManifestUrl` from the route.
- Enhance `BookmarkListViewModel` to extract `appManifestUrl` from bookmark statements when navigating to unit details.
- Simplify UI in `LearningUnitDetailScreen` by removing the subtitle from the supporting content row.

* Refactor `BookmarkListScreen` to use `PublicationListItem` and add `trailingContent` support to `PublicationListItem`.

* Remove `grade1` test case data, including `lesson002` HTML, JSON, and media assets.

* Replace duplicated getString code with new getUiTextString function

* Move PublicationListItem into its own file

* Update `.maestro/flows/002_browse_lessons_test.yaml` to include a test flow for downloading a lesson and verifying its functionality in offline mode.

* Refactor bookmark handling to utilize new XAPI constants and improve context management

* Refactor AddBookmarkUseCase and LearningUnitDetailViewModel to remove appManifestUrl handling

* Refactor AddBookmarkUseCase and LearningUnitDetailViewModel to remove appManifestUrl handling

* Enhance AddBookmarkUseCase to include title in bookmark xAPI statement

* Refactor BookmarkListViewModel and LearningUnitDetailViewModel to remove appManifestUrl handling and improve bookmark state management

* Add sorting functionality to BookmarkListViewModel and UI for bookmarks

* Add sorting functionality to BookmarkListViewModel and UI for bookmarks

* Refactor LearningUnitDetailScreen to use Column layout for improved UI structure and add app icon

* Add error handling and user feedback for bookmark operations

* Add test tags to top navigation items for improved UI testing

* Update `.maestro/flows/002_browse_lessons_test.yaml` to use element IDs instead of text-based indexing for navigating to the home screen and asserting home visibility.

* Update Maestro test flows to use resource IDs for home navigation visibility assertions.

* Update `admin_add_app.yaml` to use the resource ID `nav_home` for the home navigation tap action instead of the "Home" text label.

* Tidyup of bookmark saving to/from xAPI.

* Update `.maestro/flows/002_browse_lessons_test.yaml` to refine the navigation flow. Replace the back button action with specific navigation to the home screen and "Apps" section to access the "Statement Maker" feature.

* Refactored
The screen now:
Extracts the activityId
Passes it as Url(activityId)to uiState.taskInfoFlow()
Collects the returned flow
Renders the PublicationListItem

* Minor tidyup on homescreen.kt

* Add bookmark button back to learning unit detail screen.

* Bookmark cleanup

1) Use remember on bookmarklistscreen when collecting flow
2) bookmarklistviewmodel to filter current active user.

* Fix 002_001 browse lessons test flow.

* Tidyup bookmarks

1) Learning detail screen updated to use a shared flow to avoid unnecessarily reloading app detail
2) Use separate buttons enabled setting for bookmark button on learning unit detail to avoid potential end to end test flakiness: it is a separate load/API call.

* Resolve OpdsPublication in BookmarkListViewModel to ensure icon will display as expected if it is a relative href.

* Update demo app test to reflect navigation changes from "Apps" to "Home"

* Correct license link on DemoLaunchableAppManifestRoute.kt

* Update demo app test to use navigation ID for "Home"

* Replace tapOn home with using test tag

* Add additional logging to WebViewActivity and lesson launch to attempt to diagnose learning unit not opening flakey results on Maestro testing.

* Add more logging on xapi_statement_maker.js .

* Revert database JSON schema change: BookmarkEntity was not added when using xapi so no change.

---------

Co-authored-by: pooja &lt;pooja@ustadmobile.com&gt;
Co-authored-by: Mike Dawson &lt;mike@ustadmobile.com&gt;
</comment><date>2026-07-30 14:44:14 +0400</date><id>beec082677ecfe343236c083f1545d158453e63f</id><msg>Dev bookmark xapi (#272)</msg><path><editType>edit</editType><file>respect-app-compose/src/androidMain/kotlin/world/respect/shared/domain/license/GetLicenseLabelUseCaseAndroid.kt</file></path><path><editType>edit</editType><file>.maestro/flows/001_002_add_user_direct_test.yaml</file></path><path><editType>edit</editType><file>app-android/src/main/kotlin/world/respect/AppKoinModule.kt</file></path><path><editType>edit</editType><file>respect-server/src/main/resources/http/respect-ds/case_valid/examples/statementmaker/index.html</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/geticonforxapiactivity/GetPublicationForXapiActivityUseCase.kt</file></path><path><editType>edit</editType><file>.maestro/flows/001_001_invite_users_using_qr_code_or_link_test.yaml</file></path><path><editType>edit</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/app/AppNavHost.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/app/appstate/Snack.kt</file></path><path><editType>edit</editType><file>.maestro/flows/002_002_browse_demo_app_test.yaml</file></path><path><editType>edit</editType><file>respect-app-compose/src/androidMain/kotlin/world/respect/WebViewActivity.kt</file></path><path><editType>edit</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/app/App.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/navigation/AppRoutes.kt</file></path><path><editType>add</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/learningunit/list/PublicationListItem.kt</file></path><path><editType>edit</editType><file>respect-lib-xapi-core/src/commonMain/kotlin/world/respect/lib/xapi/model/XapiVerb.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/learningunit/detail/LearningUnitDetailViewModel.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/composeResources/values/strings.xml</file></path><path><editType>add</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/bookmark/RemoveBookmarkUseCase.kt</file></path><path><editType>edit</editType><file>respect-server/src/main/kotlin/world/respect/server/demoapp/DemoLaunchableAppManifestRoute.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/license/GetLicenseLabelUseCase.kt</file></path><path><editType>add</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/util/CommonSortOptions.kt</file></path><path><editType>edit</editType><file>.maestro/flows/subflows/admin_add_app.yaml</file></path><path><editType>edit</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/learningunit/list/LearningUnitListScreen.kt</file></path><path><editType>add</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/bookmark/BookmarkListScreen.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/apps/detail/AppsDetailViewModel.kt</file></path><path><editType>delete</editType><file>respect-datalayer-db/schemas/world.respect.datalayer.db.RespectAppDatabase/5.json</file></path><path><editType>delete</editType><file>respect-datalayer-db/schemas/world.respect.datalayer.db.RespectAppDatabase/6.json</file></path><path><editType>add</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/bookmark/BookmarkListViewModel.kt</file></path><path><editType>edit</editType><file>.maestro/flows/003_admin_user_assigns_assignment_to_a_class_test.yaml</file></path><path><editType>add</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/domain/bookmark/AddBookmarkUseCase.kt</file></path><path><editType>edit</editType><file>respect-server/src/main/resources/http/respect-ds/case_valid/js/xapi_statement_maker.js</file></path><path><editType>edit</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/learningunit/detail/LearningUnitDetailScreen.kt</file></path><path><editType>edit</editType><file>.maestro/flows/001_003_login_using_school_link_test.yaml</file></path><path><editType>edit</editType><file>respect-lib-shared/src/androidMain/kotlin/world/respect/shared/domain/launchapp/LaunchAppUseCaseAndroid.kt</file></path><path><editType>edit</editType><file>respect-lib-shared/src/commonMain/kotlin/world/respect/shared/viewmodel/apps/launcher/AppLauncherViewModel.kt</file></path><path><editType>edit</editType><file>respect-lib-xapi-core/src/commonMain/kotlin/world/respect/lib/xapi/OpenEelXapiConstants.kt</file></path><path><editType>edit</editType><file>.maestro/flows/002_001_browse_lessons_test.yaml</file></path><path><editType>edit</editType><file>respect-app-compose/src/commonMain/kotlin/world/respect/app/view/home/HomeScreen.kt</file></path><path><editType>add</editType><file>respect-lib-shared/src/commonMain/composeResources/drawable/no_bookmark.xml</file></path></item><kind>git</kind></changeSet><culprit><absoluteUrl>https://devserver3.ustadmobile.com/jenkins/user/noreply</absoluteUrl><fullName>noreply</fullName></culprit></freeStyleBuild>