Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
febee98
fixes extra gap b/w lines in paragraph mode off
MySmilingTurban Jan 21, 2023
ca5c528
fixes extra gap b/w lines in paragraph mode off
MySmilingTurban Jan 21, 2023
c05162c
fix: trackplayer interactions and performance optimisations
manjotkaur27 Mar 13, 2026
255b941
fix: inverse playback speed buttons, track stopping on switching menu…
manjotkaur27 Mar 15, 2026
9d4a98f
fix: incorrect track current and total duration displayed sometimes
manjotkaur27 Mar 15, 2026
9277cfc
fix: progress bar of audio takes time to update when coming back from…
manjotkaur27 Mar 15, 2026
bbc66c6
fix: add hyperlink indication ui to request bani audio
manjotkaur27 Mar 15, 2026
2fd909d
Audio starts auto playing when its paused after a new app audio/calls
manjotkaur27 Mar 15, 2026
a4510cf
fix: Increase/decrease in volume causes audio to pause (intermittent)
manjotkaur27 Mar 15, 2026
e5caff8
fix: incorrect track durations, revert enable audio play in other menus
manjotkaur27 Mar 16, 2026
363fc5e
fix: bg audio play mixes with other audio, incorrect audiop duration
manjotkaur27 Mar 16, 2026
8626cf1
Delete manifest-endpoint-audit.csv
bhuveshx Mar 16, 2026
47f0a1f
Delete json-availability-audit.csv
bhuveshx Mar 16, 2026
a3e4578
fix: translation and transliteration setting flows
manjotkaur27 Mar 16, 2026
db56abe
fix: artist pick preview, add tests
manjotkaur27 Mar 17, 2026
457af55
fix: audio player and autoplay setting flows
manjotkaur27 Mar 17, 2026
4886eb0
fix: bani 6 api, bani starting not starting in read mode
manjotkaur27 Mar 19, 2026
54783e9
fix: manual test cases bugs
manjotkaur27 Mar 19, 2026
3a5f661
selected artist in preview should start audio withoout pressign play
manjotkaur27 Mar 19, 2026
efeb07a
fix: cache limit to 5 last played tracks, remove sync scroll in preview
manjotkaur27 Mar 19, 2026
fb3cd4d
add new audios and jsons
manjotkaur27 Mar 20, 2026
a33317d
fix: sync w/ scroll, remember sync preference, no internet falbacks
manjotkaur27 Mar 21, 2026
498a04c
fix: connection loss fallbacks
manjotkaur27 Mar 21, 2026
07c78a7
fix: preview issues
manjotkaur27 Mar 21, 2026
3d7c9be
fix: seeking issues
manjotkaur27 Mar 21, 2026
c40d5cc
fix: artist cache rem
manjotkaur27 Mar 21, 2026
302a880
fix: post menu browse preview list popup open fail
manjotkaur27 Mar 21, 2026
a988833
fix: bg play:
manjotkaur27 Mar 22, 2026
9d56a30
fix: update test scripts
manjotkaur27 Mar 23, 2026
be2ed31
Delete generate_test_map.py
bhuveshx Mar 24, 2026
4a9fbe6
fix: WebView fix for iOS
manjotkaur27 Mar 24, 2026
deff66d
fix: settings page alighments, transliteration and translation menu size
manjotkaur27 Mar 26, 2026
b13958b
fix: added icon/art cosmetics to noti track player
manjotkaur27 Mar 26, 2026
4ed7a3a
fix: duck and call/alarm flows, bani name in noti audio player
manjotkaur27 Mar 26, 2026
1abcd4d
fix: scrollbar color inconsistency
manjotkaur27 Mar 26, 2026
2c9302e
fix: autoscroll component
manjotkaur27 Mar 26, 2026
339a872
fix: mutex autoscroll and audio player
manjotkaur27 Mar 26, 2026
7eb3074
fix: 250ms polling for progress for snappy sync scroll
manjotkaur27 Mar 26, 2026
9476676
fix: immersive mode and fix navbar size
manjotkaur27 Mar 26, 2026
5d69b6a
add new jsons and mp3 urls
manjotkaur27 Mar 26, 2026
c2d105b
fix: button bgs on iOS
manjotkaur27 Mar 26, 2026
9fea116
fix: bani name in noti player
manjotkaur27 Mar 26, 2026
2550a0e
fix: mute issue on large audios
manjotkaur27 Mar 26, 2026
27e6e25
ship with sync scroll ON
manjotkaur27 Mar 26, 2026
7034a7c
json bundle, network improvements
manjotkaur27 Mar 27, 2026
6bf099f
fix iOS back icon background
manjotkaur27 Mar 27, 2026
782aa81
add giani gurdev ji audios, add horizontal read progress, fix muting …
manjotkaur27 Mar 27, 2026
b9e8b51
fix: update test scripts for new code
manjotkaur27 Mar 28, 2026
4544bd5
revert to slider for auto-scroll component
manjotkaur27 Mar 31, 2026
95f8ee3
add audio enable in navbar in autoscroll mode, fix gap in multi-optio…
manjotkaur27 Mar 31, 2026
2eabba7
fix: downloading indicator, revert to native bridge progress bar
manjotkaur27 Mar 31, 2026
d3444d2
shift constants to constant.js, add hindi locale for RELOADING_BANI
manjotkaur27 Mar 31, 2026
2de630c
revert to old design for sync scroll, fix navbar interaction with audio
manjotkaur27 Apr 1, 2026
2330e6b
fix: faster checking and synchronous guard for sync scroll
manjotkaur27 Apr 1, 2026
3cd2f0b
add missing data for Giani Gurdev Singh ji
manjotkaur27 Apr 2, 2026
0343db5
FIX: Audio & text discrepency bug fix
smanjot27 Apr 2, 2026
ba781ba
fix: increase speed of autoscroll, autoscroll dialog box content size
manjotkaur27 Apr 2, 2026
c0d74a6
fix: sync scroll on android by shifting whole app to .m4a audio files
manjotkaur27 Apr 5, 2026
d58bb1a
chore: remove unused imports, variables and dead duckPauseTimer code
manjotkaur27 Apr 5, 2026
38b9e3b
Update README
manjotkaur27 Apr 6, 2026
5552448
fix: call pause() instead of reset () on RemoteDuck
manjotkaur27 Apr 7, 2026
bdea378
fix: bg play in iOS with another app in focus
manjotkaur27 Apr 9, 2026
90dd846
Revert "fix: bg play in iOS with another app in focus"
smanjot27 Apr 9, 2026
55cbe5c
FIX: iOS player functioning in notification panel
manjotkaur27 Apr 9, 2026
21b5ec1
add fixed japji sahib json for bhai jarnail singh
manjotkaur27 Apr 9, 2026
2911600
fix: scroll and next button in artist list
manjotkaur27 Apr 11, 2026
0e6cb0c
fix: error/disable message popups text and theme
manjotkaur27 Apr 11, 2026
4af4a4a
fix: network error popup, unintended resume on autoplay off
manjotkaur27 Apr 11, 2026
dd4b1c5
fix: Gurbani Akhar Thick font face typo
manjotkaur27 Apr 11, 2026
1093b25
fix: bani folder pages names in different transliteration
manjotkaur27 Apr 13, 2026
0d96808
Fix: Appbar Modification in Bookmark screen for iOS
manjotkaur27 Apr 15, 2026
1da9626
fix: autoplay behaviour on calls, japji sahib pauri 34 incorrect string
manjotkaur27 Apr 15, 2026
67a70f8
fix: x padding
manjotkaur27 Apr 16, 2026
2843936
fix bookmark appbar color in light mode
manjotkaur27 Apr 17, 2026
f323498
fix: autoplay on interactions on focus gain
manjotkaur27 Apr 17, 2026
95f8a5b
Improvement: Consistent Toggle UI in android & iOS in both modes (No …
manjotkaur27 Apr 18, 2026
fe5d393
fix: Status bar icon & visibility according to toggle
manjotkaur27 Apr 18, 2026
2cfc9fc
fix: instantl sync of autoscroll& keep screen awake toggle
manjotkaur27 Apr 18, 2026
ff2ba1a
fix: preserve read context when switching to paragraph mode in auto s…
manjotkaur27 Apr 20, 2026
91612a8
fix: cache read progress in auto scroll in closed & terminated app state
manjotkaur27 Apr 21, 2026
989d83f
FIX:
manjotkaur27 Apr 23, 2026
74813ee
fix: bani length mapping holds true of audios when avail
manjotkaur27 Apr 24, 2026
42c1ebb
FIX:
manjotkaur27 Apr 24, 2026
fc545d0
fix: audio should not play in background when auto play is on & bani …
manjotkaur27 Apr 24, 2026
5c9522e
iOS Compatibility fixes
manjotkaur27 Apr 25, 2026
f22fc62
fix: update test scripts and add fix for iPad read progress
manjotkaur27 Apr 25, 2026
82f7e36
Fix: Notification player & read progress cache in iPad
manjotkaur27 Apr 25, 2026
1df8ca0
Fix: audio should not resume in background on change bani length from…
manjotkaur27 Apr 25, 2026
5c91aeb
activate bani id 1000, anand sahib 6 pauri
manjotkaur27 Apr 26, 2026
def9384
fix: remove explicit toggle messages, length/avail based Maafi message
manjotkaur27 Apr 30, 2026
36599ce
fix: Google form for Maafi page, fix higlight width and english trans…
manjotkaur27 Apr 30, 2026
db94548
fix: multi higlight in sync scroll
manjotkaur27 Apr 30, 2026
64a4940
fix: onboarding resize
manjotkaur27 May 2, 2026
b5b8f52
fix: trimmed banis audio lengths, dynamic length maafi message
manjotkaur27 May 7, 2026
4ea9589
fix: audio end should reset player
manjotkaur27 May 7, 2026
91383f2
fix: text visiblity when language is changed
manjotkaur27 May 7, 2026
8a50094
fix: perserve selected language even when app is closed
manjotkaur27 May 7, 2026
73fe8cd
fixes
manjotkaur27 May 8, 2026
37ef164
fix: stale progress on bani length change
manjotkaur27 May 9, 2026
3dbb591
fix: switch japji sahib m4a/json bhai jarnail singh
manjotkaur27 May 9, 2026
53b973e
fix highlight behaviour on focus loss and pause + add logging
manjotkaur27 May 11, 2026
122b40e
fix: audio button visibilitiy on manual autoscroll toggle off
manjotkaur27 May 11, 2026
98996a4
fix: flash of saved progress from other last played track
manjotkaur27 May 13, 2026
af77664
fix: progress update
manjotkaur27 May 13, 2026
1695583
fix: iOS bugs
manjotkaur27 May 19, 2026
01f6a74
fix: consistent artist names, warning on Baloo Paaji font selection
manjotkaur27 May 19, 2026
6c33d05
keep original tracks only for length affected banis
manjotkaur27 May 20, 2026
8732efe
fix: analytics, tests
manjotkaur27 May 28, 2026
b7292db
fix: prevent ForegroundServiceStartNotAllowedException crash on Andro…
manjotkaur27 May 28, 2026
65a9f32
fix: notification ducking, add bani_title to track_download firebase …
manjotkaur27 May 28, 2026
4aaa86a
fix: guard corrupt/partial downloads — validate against trackSizeMB b…
manjotkaur27 May 28, 2026
0516a6b
Add PROJECT_STRUCTURE.md
manjotkaur27 May 28, 2026
1be9cd9
Improvements requested in Review:
manjotkaur27 Jun 19, 2026
ea0e97e
feat(reader): hide bottom nav with the header on tap/scroll
manjotkaur27 Jun 30, 2026
1b88695
feat(audio): serve audio/lyrics from the Azure Front Door CDN
manjotkaur27 Jun 30, 2026
8ae593b
Improvements
manjotkaur27 Jul 2, 2026
f85df3a
Improvementts: Hide Nav Bar on scroll & tap
manjotkaur27 Jul 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ android/node
node_modules/
npm-debug.log
yarn-error.log

# BUCK
buck-out/
\.buckd/
*.keystore
!debug.keystore
*.jks

# fastlane
#
Expand All @@ -63,6 +63,7 @@ buck-out/
# Bundle artifact
*.jsbundle


# Ruby / CocoaPods
**/Pods/
/vendor/bundle/
Expand All @@ -79,4 +80,6 @@ buck-out/
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
!.yarn/versions

android/app/release/app-release/
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,31 @@ Run tests with:
yarn test
```

## 🎵 Audio Assets (M4A)

All audio files used in this app are in **M4A format** (AAC 128kbps inside an MP4 container). M4A is required over MP3 because ExoPlayer on Android can seek accurately within M4A files using the container's built-in index — this is what makes sync scroll work correctly on Android. MP3 seeking is estimate-based and causes progressive drift.

### Creating M4A Files

To convert a source audio file to the correct M4A format:

```bash
ffmpeg -y -i input.mp3 -codec:a aac -b:a 128k -map_metadata 0 -movflags +faststart output.m4a
```

- `-codec:a aac` — encodes audio as AAC inside an MP4 container
- `-b:a 128k` — 128kbps constant bitrate
- `-movflags +faststart` — moves the MP4 index (`moov` atom) to the front of the file so ExoPlayer can begin streaming instantly with a single HTTP request. **This flag is mandatory** — without it, streaming triggers multiple network round-trips before playback can start
- `-map_metadata 0` — preserves original metadata tags

### Important Notes

- **Never use MP3** — ExoPlayer's inaccurate seeking on MP3 breaks sync scroll on Android
- **Always include `-movflags +faststart`** — skipping it will cause buffering on stream seek
- **File naming**: Use PascalCase (e.g. `JapjiSahib.m4a`, not `japji-sahib.m4a`)

---

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
Expand Down Expand Up @@ -239,4 +264,4 @@ For information, suggestions, or help, visit:
<a href="https://www.banidb.com/">
<img src="images/banidb-logo-full.png" alt="BaniDB" width="200" style="border-radius: 10px; margin: 10px;" />
</a>
</div>
</div>
5 changes: 4 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply plugin: "com.google.gms.google-services"
apply plugin: "com.google.firebase.crashlytics"
apply plugin: "com.google.firebase.firebase-perf"
// firebase-perf plugin removed: the firebase-perf library and @react-native-firebase/perf
// package are not in the project dependencies. The plugin rewrites OkHttp bytecode to inject
// FirebasePerfOkHttpClient, which causes a NoClassDefFoundError crash at startup when the
// library is absent. Re-add both the library and this plugin together if perf monitoring is needed.


/**
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
</activity>

<service android:name="com.doublesymmetry.trackplayer.service.MusicService"
android:label="@string/app_name"
android:foregroundServiceType="mediaPlayback"
android:exported="true"
tools:replace="android:exported" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import android.view.KeyEvent
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat

class MainActivity : ReactActivity() {

Expand All @@ -21,8 +24,33 @@ class MainActivity : ReactActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
SplashScreen.show(this)
super.onCreate(null);
}
super.onCreate(null)
// Lay out content edge-to-edge so the window draws behind system bars.
WindowCompat.setDecorFitsSystemWindows(window, false)
}

/**
* Called every time the window regains/loses focus. We re-apply sticky-immersive
* flags here so they survive notification shade pulls, lock/unlock cycles, etc.
*/
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
hideSystemBars()
}
}

/**
* Set BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE so the system bars (status bar +
* gesture navigation bar) are hidden by default and reappear transiently when
* the user swipes from an edge, then auto-hide again without any app interaction.
*/
private fun hideSystemBars() {
val controller = WindowInsetsControllerCompat(window, window.decorView)
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
controller.hide(WindowInsetsCompat.Type.systemBars())
}

/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
Expand Down
Comment thread
manjotkaur27 marked this conversation as resolved.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion android/app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary_dark">#2a3381</color>
<color name="primary_dark">#113979</color>
<color name="primary_variant">#171d47dd</color>
<color name="primary_accent">#5195ea</color>
</resources>
5 changes: 5 additions & 0 deletions android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<item name="colorPrimaryDark">@color/primary_variant</item>
<item name="colorAccent">@color/primary_accent</item>
<item name="android:scrollbarThumbVertical">@drawable/scrollbar_vertical_thumb</item>
<!-- Edge-to-edge: draw content behind display cutouts (notches/punch-holes) -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<!-- Make navigation bar and status bar transparent so app draws underneath -->
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>

<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
Expand Down
44 changes: 38 additions & 6 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,69 @@
import React, { useEffect } from "react";
import { AppState } from "react-native";
import ErrorBoundary from "react-native-error-boundary";
import { SafeAreaProvider } from "react-native-safe-area-context";
import SplashScreen from "react-native-splash-screen";
import Toast from "react-native-toast-message";
import toastConfig from "./src/common/toastConfig";
import { Provider } from "react-redux";
import notifee, { EventType } from "@notifee/react-native";
import { PersistGate } from "redux-persist/integration/react";
import {
createStore,
STRINGS,
logError,
initializeCrashlytics,
FallBack,
resetBadgeCount,
navigateTo,
initializePerformanceMonitoring,
} from "@common";
import ThemeProvider from "./src/common/context/ThemeProvider";
import { TrackPlayerSetup } from "./src/common/TrackPlayerUtils";
import Navigation from "./src/navigation";

const { store, persistor } = createStore();

/**
* After redux-persist rehydrates the store, sync the localization library
* with the persisted language. Without this, STRINGS stays on the default
* locale (English) because redux-persist's REHYDRATE action does not
* trigger the setLanguage action creator where STRINGS.setLanguage() lives.
*/
const handleBeforeLift = () => {
const { language } = store.getState();
if (language) {
STRINGS.setLanguage(language);
}
};

const App = () => {
useEffect(() => {
// Code to run on component mount
SplashScreen.hide(); // Hide the splash screen once everything is loaded
}, []); // The empty array causes this effect to only run on mount

useEffect(() => {
(async () => {
await initializePerformanceMonitoring();
const runSetup = async () => {
await initializeCrashlytics();
await TrackPlayerSetup();
})();
};

// Guard against OS-initiated background cold starts (service revival, FCM,
// Bluetooth events). startForeground() is blocked in background-restricted
// states on Android 12+, so we must not call setupPlayer() until the app is
// actually in the foreground. On a normal launcher tap AppState is already
// 'active' and we run immediately with no overhead.
if (AppState.currentState !== "active") {
const sub = AppState.addEventListener("change", (state) => {
if (state === "active") {
sub.remove();
runSetup().catch(logError);
}
});
return () => sub.remove();
}

runSetup().catch(logError);
}, []);

useEffect(() => {
Expand All @@ -51,12 +83,12 @@ const App = () => {

return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<PersistGate loading={null} persistor={persistor} onBeforeLift={handleBeforeLift}>
<ThemeProvider>
<ErrorBoundary onError={logError} FallbackComponent={FallBack}>
<SafeAreaProvider>
<Navigation />
<Toast />
<Toast config={toastConfig} />
</SafeAreaProvider>
</ErrorBoundary>
</ThemeProvider>
Expand Down
Loading