-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Introduce book detail screen, global player, smart rewind settings, and enhance content caching and player UI. #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
428b273
f72609b
c8435e2
0838597
cb86e43
df7e6bf
676183e
78bf29f
97d779a
81c9418
5aad959
51068cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||
| --- | ||||||
| trigger: always_on | ||||||
| --- | ||||||
|
|
||||||
| # Project Context and Guidelines | ||||||
|
|
||||||
| ## About Project | ||||||
|
|
||||||
| This is an offline-first Android client app for the [audiobookshelf](https://github.com/advplyr/audiobookshelf) server. | ||||||
|
|
||||||
| ## Feature Requirements (Offline first behavior) | ||||||
|
|
||||||
| - As the app is an offline-first app, assume that the server is not always reachable. | ||||||
| - Playback progress should be saved in the local database first **immediately**. | ||||||
| - The app should watch the network changes, such as connecting to a new wifi network, or Ethernet LAN, or disconnecting from a network and connecting to a new network, disconnecting from wifi and connecting to celular network, etc., and try to ping or reach out to the audiobook server to check whether the server is reachable. | ||||||
| - If the server is reachable, the app should sync the local progress to the server and pull the latest progress updates from the server to the local database; it should merge the updates from both. | ||||||
| - If the server is reachable, and some chapters of any audiobook are downloaded, i.e., available offline, then the offline track should be given priority for playback. | ||||||
| - If the offline track is deleted/cleared while the book is being played, the player should attempt to fallback to the online URL if the server is reachable, otherwise pause playback and persist the last playback state (track ID, playback position/timestamp, current chapter/index, and playback status) plus a flag indicating offline content was removed; ensure the rule notes that these persisted fields are used to resume or report playback state and are written atomically to the player state store. | ||||||
| - The app must be fully functional for downloaded content when offline. | ||||||
|
|
||||||
| ## Ensure Stability | ||||||
|
|
||||||
| - Ensure null-safety when converting data (e.g., check for division by zero in percentage calculations). | ||||||
| - Changes must be verified by building the app and ensuring logic holds (e.g., uninstall/reinstall for clean state tests). | ||||||
|
|
||||||
| ## Overall Functionality | ||||||
|
|
||||||
| - When the app loads, it should load the offline available book content immediately, then in the background reach out to the server (if the server is reachable) and fetch the full list of the books, continue listening section books and update the UI seemlessly. | ||||||
| - The app should cache all the book's metadata in local database to optimise the app load time, Only the chapters / audio tracks should not be cached automatically / by default. Chapters should be downloaded and cached on demand by the user, using the download chapters/book functionality. | ||||||
| - When the app loads, if the server is not reachable, it shouldn't show long loading screen, trying to fetch the books from the server, it should load the book's list from the local database, however it should only show the books whos' chapters are downloaded and available offline can be played. | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix grammar error: "whose" (no apostrophe). The possessive form should be "whose", not "whos'". 🔎 Proposed fix-- When the app loads, if the server is not reachable, it shouldn't show long loading screen, trying to fetch the books from the server, it should load the book's list from the local database, however it should only show the books whos' chapters are downloaded and available offline can be played.
+- When the app loads, if the server is not reachable, it shouldn't show long loading screen, trying to fetch the books from the server, it should load the book's list from the local database, however it should only show the books whose chapters are downloaded and available offline can be played.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| - When the server becomes reachable, it should update the books list, as now all the books can be played from local cache or online from the server. | ||||||
| - When the network is switched, the app should trigger checking whether the server is still reachable or not, if not reachable, it should update the UI to only show offline available ready to play books. | ||||||
SurjitSahoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
| ## General Guidelines and Standards | ||||||
|
|
||||||
| - **Colors**: Must be referenced from `Color.kt` / `Theme.kt`. Do not use raw hex values (e.g., `0xFF...`) in Composables. | ||||||
| - **Dimensions**: Must use `Spacing.kt` (e.g., `Spacing.md`, `Spacing.lg`) for padding, margins, and layout dimensions. | ||||||
| - **Design System**: Adhere effectively to the spacing system and color palette defined in the project. | ||||||
| - **ABSOLUTELY NO** hardcoded user-facing strings in UI code. All strings must be extracted to `strings.xml` and accessed via `stringResource`. | ||||||
| - Use `associateBy` or proper indexing for collection lookups (O(1)) instead of nested loops (O(N^2)) when synchronizing data. | ||||||
| - Avoid expensive operations on the main thread. | ||||||
| - No code duplication, keep the code clean and easy to maintain. | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,53 @@ | ||||||||||||
| name: Build and Release Kahani | ||||||||||||
|
|
||||||||||||
| on: | ||||||||||||
| push: | ||||||||||||
| branches: | ||||||||||||
| - main | ||||||||||||
| pull_request: | ||||||||||||
| branches: | ||||||||||||
| - main | ||||||||||||
| workflow_dispatch: | ||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
|
||||||||||||
| jobs: | ||||||||||||
| release: | ||||||||||||
| name: Build Signed APK | ||||||||||||
| runs-on: ubuntu-latest | ||||||||||||
| steps: | ||||||||||||
| - name: Checkout Code | ||||||||||||
| uses: actions/checkout@v4 | ||||||||||||
| with: | ||||||||||||
| fetch-depth: 0 | ||||||||||||
|
|
||||||||||||
| - name: Set up JDK 21 | ||||||||||||
| uses: actions/setup-java@v4 | ||||||||||||
| with: | ||||||||||||
| distribution: 'zulu' | ||||||||||||
| java-version: '21' | ||||||||||||
| cache: 'gradle' | ||||||||||||
|
|
||||||||||||
| - name: Decode Keystore | ||||||||||||
| run: | | ||||||||||||
| echo "${{ secrets.RELEASE_KEYSTORE_BASE64 }}" | base64 --decode > app/kahani-release.jks | ||||||||||||
|
|
||||||||||||
| - name: Build Release APK | ||||||||||||
| run: ./gradlew assembleRelease | ||||||||||||
| env: | ||||||||||||
| RELEASE_STORE_FILE: kahani-release.jks | ||||||||||||
| RELEASE_STORE_PASSWORD: ${{ secrets.RELEASE_PASSWORD }} | ||||||||||||
| RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }} | ||||||||||||
| RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} | ||||||||||||
|
|
||||||||||||
| - name: Create Release | ||||||||||||
| uses: softprops/action-gh-release@v1 | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update to latest action version. The ⬆️ Proposed fix - name: Create Release
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v2
with:
files: app/build/outputs/apk/release/app-release.apkFor better security and stability, consider pinning to a specific commit SHA: - uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.4Based on static analysis hints. 📝 Committable suggestion
Suggested change
🧰 Tools🪛 actionlint (1.7.10)42-42: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue (action) 🤖 Prompt for AI Agents |
||||||||||||
| with: | ||||||||||||
| files: app/build/outputs/apk/release/app-release.apk | ||||||||||||
| tag_name: v${{ github.run_number }} | ||||||||||||
| name: Release v${{ github.run_number }} | ||||||||||||
| body: | | ||||||||||||
| Automated Release for Kahani. | ||||||||||||
| Commit: ${{ github.sha }} | ||||||||||||
| draft: false | ||||||||||||
| prerelease: false | ||||||||||||
| env: | ||||||||||||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,3 +35,4 @@ google-services.json | |
|
|
||
| # Schemas | ||
| app/schemas | ||
| .DS_Store | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||
| { | ||||||
| "version": "2.0.0", | ||||||
| "tasks": [ | ||||||
| { | ||||||
| "type": "gradle", | ||||||
| "id": "${workspaceFolder}app:installDebugapp", | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the malformed task ID. The task ID appears to have a concatenation issue: 🔎 Proposed fix- "id": "${workspaceFolder}app:installDebugapp",
+ "id": "${workspaceFolder}/app:installDebug:app",📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| "script": "app:installDebug", | ||||||
| "description": "Installs the Debug build.", | ||||||
| "group": "install", | ||||||
| "project": "app", | ||||||
| "buildFile": "${workspaceFolder}/app/build.gradle.kts", | ||||||
| "rootProject": "Lissen", | ||||||
| "projectFolder": "${workspaceFolder}", | ||||||
| "workspaceFolder": "${workspaceFolder}", | ||||||
| "args": "", | ||||||
| "javaDebug": false, | ||||||
| "problemMatcher": ["$gradle"], | ||||||
| "label": "gradle: app:installDebug" | ||||||
| } | ||||||
| ] | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -50,11 +50,11 @@ android { | |||||||||||||||||||||||||
| defaultConfig { | ||||||||||||||||||||||||||
| val commitHash = gitCommitHash() | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| applicationId = "org.grakovne.lissen" | ||||||||||||||||||||||||||
| applicationId = "org.surjit.kahani" | ||||||||||||||||||||||||||
| minSdk = 28 | ||||||||||||||||||||||||||
| targetSdk = 36 | ||||||||||||||||||||||||||
| versionCode = 10800 | ||||||||||||||||||||||||||
| versionName = "1.8.0-$commitHash" | ||||||||||||||||||||||||||
| versionCode = 10000 | ||||||||||||||||||||||||||
| versionName = "1.0.0-${commitHash}" | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| applicationId = "org.surjit.kahani" | |
| minSdk = 28 | |
| targetSdk = 36 | |
| versionCode = 10800 | |
| versionName = "1.8.0-$commitHash" | |
| versionCode = 10000 | |
| versionName = "1.0.0-${commitHash}" | |
| applicationId = "org.surjit.kahani" | |
| minSdk = 28 | |
| targetSdk = 36 | |
| versionCode = 10900 | |
| versionName = "1.0.0-${commitHash}" |
🤖 Prompt for AI Agents
In @app/build.gradle.kts around lines 53 - 57, The PR lowers versionCode and
changes applicationId, which will break updates; restore versionCode to a value
>= the previous production value (e.g., set versionCode to at least 10800 or
bump to a new higher integer) in the build script where versionCode is set, and
only change applicationId (org.surjit.kahani) if you intend this to be a new
app—if so, document that this is a deliberate rebranding and verify users must
reinstall and a data migration plan exists; otherwise revert applicationId to
the original (org.grakovne.lissen) to preserve update continuity.
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| <resources> | ||
| <string name="app_name">Lissen (DEBUG)</string> | ||
| </resources> | ||
| <string name="app_name">Kahani (DEBUG)</string> | ||
| </resources> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,7 @@ | |
| android:roundIcon="@mipmap/ic_launcher_round" | ||
| android:supportsRtl="true" | ||
| android:largeHeap="true" | ||
| android:theme="@style/Theme.Lissen" | ||
| android:theme="@style/Theme.Kahani" | ||
| tools:ignore="DiscouragedApi,UnusedAttribute" | ||
| android:manageSpaceActivity="org.grakovne.lissen.content.LissenDataManagementActivity" | ||
| tools:targetApi="36"> | ||
|
|
@@ -41,7 +41,7 @@ | |
| android:name=".ui.activity.AppActivity" | ||
| android:exported="true" | ||
| android:launchMode="singleTop" | ||
| android:theme="@style/Theme.Lissen" | ||
| android:theme="@style/Theme.Kahani" | ||
| tools:ignore="LockedOrientationActivity"> | ||
| <intent-filter> | ||
| <action android:name="android.intent.action.MAIN" /> | ||
|
|
@@ -68,7 +68,7 @@ | |
| <category android:name="android.intent.category.BROWSABLE" /> | ||
|
|
||
| <data | ||
| android:scheme="lissen" | ||
| android:scheme="kahani" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for any remaining references to "lissen" OAuth scheme
rg -in 'lissen' --type xml --type kt --type java --type md --type gradleRepository: SurjitSahoo/lissen-up Length of output: 91 🏁 Script executed: #!/bin/bash
# Check the context in AndroidManifest.xml around the kahani scheme
cat -n app/src/main/AndroidManifest.xml | grep -A 5 -B 5 'kahani'Repository: SurjitSahoo/lissen-up Length of output: 474 🏁 Script executed: #!/bin/bash
# Look for OAuth-related configurations or documentation
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "README*" \) | head -20 | xargs grep -l -i 'oauth\|redirect' 2>/dev/null | head -10Repository: SurjitSahoo/lissen-up Length of output: 47 🏁 Script executed: #!/bin/bash
# Search for any remaining references to "lissen" with correct file types
rg -in 'lissen' --type xml --type kotlin --type java --type mdRepository: SurjitSahoo/lissen-up Length of output: 50378 🏁 Script executed: #!/bin/bash
# Look for OAuth-related code and configuration
rg -in 'oauth|redirect.*uri' --type xml --type kotlin --type java --type md -A 2 -B 2Repository: SurjitSahoo/lissen-up Length of output: 23846 🏁 Script executed: #!/bin/bash
# Check build.gradle files and other configuration for OAuth setup
find . -type f -name "*.gradle" -o -name "build.gradle.kts" | xargs grep -i 'oauth\|audiobookshelf' 2>/dev/nullRepository: SurjitSahoo/lissen-up Length of output: 49 🏁 Script executed: #!/bin/bash
# Search for any migration-related code or version handling
rg -in 'migration|migrate|scheme.*change' --type kotlin --type java --type xmlRepository: SurjitSahoo/lissen-up Length of output: 6395 🏁 Script executed: #!/bin/bash
# Verify the AuthScheme constant value
cat -n app/src/main/kotlin/org/grakovne/lissen/channel/audiobookshelf/common/oauth/OAuthScheme.ktRepository: SurjitSahoo/lissen-up Length of output: 261 🏁 Script executed: #!/bin/bash
# Check how AuthScheme is used in the OAuth flow
rg -A 2 -B 2 'AuthScheme.*://' app/src/main/kotlin/org/grakovne/lissen/channel/audiobookshelf/common/api/AudiobookshelfAuthService.ktRepository: SurjitSahoo/lissen-up Length of output: 384 Update AuthScheme constant to match the AndroidManifest.xml change. The OAuth scheme was updated in Update line 3 in const val AuthScheme = "kahani"Additionally, confirm with users that re-authentication is required after this change. 🤖 Prompt for AI Agents |
||
| android:host="oauth" /> | ||
| </intent-filter> | ||
| </activity> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix spelling error: "seamlessly".
The word "seemlessly" is misspelled; it should be "seamlessly".
🔎 Proposed fix
🤖 Prompt for AI Agents