diff --git a/README.md b/README.md index 926527c..4aa4910 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ *Our song*: a music app for the Badaga people of the Nilgiris. Flutter app for iOS and Android. - Plan: [docs/NK_IMPLEMENTATION_PLAN.md](docs/NK_IMPLEMENTATION_PLAN.md) +- Store release (Codemagic, TestFlight, Play): [docs/app-store-release.md](docs/app-store-release.md) - Design canvas: https://claude.ai/artifact/9ZLCbGn4rUTVTqfRXTtMkq ## Run diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index bd49c2f..283a978 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,9 +1,19 @@ +import java.util.Properties + plugins { id("com.android.application") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") } +// Release signing: android/key.properties on a developer machine, or the CM_KEYSTORE_* variables +// that Codemagic sets. Without either, release builds fall back to the debug key (local testing only). +val keyProps = Properties().apply { + val f = rootProject.file("key.properties") + if (f.exists()) f.inputStream().use { load(it) } +} +val releaseStoreFile: String? = keyProps.getProperty("storeFile") ?: System.getenv("CM_KEYSTORE_PATH") + android { namespace = "com.metatroncubesolutions.nanga_kathai" compileSdk = flutter.compileSdkVersion @@ -15,7 +25,6 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId = "com.metatroncubesolutions.nanga_kathai" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. @@ -29,11 +38,20 @@ android { versionName = flutter.versionName } + signingConfigs { + if (releaseStoreFile != null) { + create("release") { + storeFile = file(releaseStoreFile) + storePassword = keyProps.getProperty("storePassword") ?: System.getenv("CM_KEYSTORE_PASSWORD") + keyAlias = keyProps.getProperty("keyAlias") ?: System.getenv("CM_KEY_ALIAS") + keyPassword = keyProps.getProperty("keyPassword") ?: System.getenv("CM_KEY_PASSWORD") + } + } + } + buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") + signingConfig = signingConfigs.getByName(if (releaseStoreFile != null) "release" else "debug") } } } diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..77615a9 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,12 +1,5 @@ - + - - - - + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..77615a9 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,5 @@ - + - - - - + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..80b730f --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..b051ea1 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..4b4052e Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..5338d16 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..dc6c150 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..d79be9f 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..6ed082e Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..38982f4 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..a37a5b1 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..7ba0c81 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..7b27b98 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..177b7bb --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,5 @@ + + + #FDFCF5 + #0B1A14 + diff --git a/assets/brand/app_icon_1024.png b/assets/brand/app_icon_1024.png new file mode 100644 index 0000000..5f8d479 Binary files /dev/null and b/assets/brand/app_icon_1024.png differ diff --git a/assets/brand/app_icon_foreground.png b/assets/brand/app_icon_foreground.png new file mode 100644 index 0000000..4aeb93a Binary files /dev/null and b/assets/brand/app_icon_foreground.png differ diff --git a/assets/brand/play_store_icon_512.png b/assets/brand/play_store_icon_512.png new file mode 100644 index 0000000..8ca3a69 Binary files /dev/null and b/assets/brand/play_store_icon_512.png differ diff --git a/codemagic.yaml b/codemagic.yaml new file mode 100644 index 0000000..68e8c05 --- /dev/null +++ b/codemagic.yaml @@ -0,0 +1,107 @@ +# Codemagic builds for Nanga Kathai. Setup steps: docs/app-store-release.md +# +# Needed in Codemagic (Team settings / app settings): +# - Environment variable group "nk_app": SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, MEDIA_BASE_URL +# - App Store Connect API key integration named "NK App Store Connect" (iOS) +# - Android keystore uploaded with reference name "nk_upload_keystore" (Android) +# - Variable GCLOUD_SERVICE_ACCOUNT_CREDENTIALS in group "nk_google_play" (Android publishing) + +definitions: + write_env: &write_env + name: Write env.json from Codemagic variables + script: | + cat > env.json < Environment variables and create the group **`nk_app`** with: + - `SUPABASE_URL` = `https://app.nkbmusic.com` + - `SUPABASE_PUBLISHABLE_KEY` = the value from your local `env.json` + - `MEDIA_BASE_URL` = `https://app.nkbmusic.com/storage/v1/object/public/audio` +2. **App Store Connect API key.** + - In App Store Connect, open Users and Access > Integrations > App Store Connect API and generate a key with the **App Manager** role. + - In Codemagic, open Team settings > Team integrations > Developer Portal and add the key with the name **`NK App Store Connect`**. +3. **iOS signing.** Open Team settings > codemagic.yaml settings > Code signing identities. + - Under iOS certificates, generate an **Apple Distribution** certificate. + - Under iOS provisioning profiles, fetch the **App Store** profile for `com.metatroncubesolutions.nangaKathai`. Create that profile on developer.apple.com first if it doesn't exist (see step 3.1). +4. **Android signing.** On the same page, under Android keystores, upload + `C:\Users\manes\nk-keys\nk-upload.jks` with the reference name **`nk_upload_keystore`**, + alias `upload`. The password is in `C:\Users\manes\nk-keys\key.properties.backup`. +5. **Google Play publishing (optional).** + - Create a Google Cloud service account, invite it in Play Console > Users and permissions with release rights, and download its JSON key. + - Store the key as `GCLOUD_SERVICE_ACCOUNT_CREDENTIALS` (secure) in a variable group **`nk_google_play`**. + +## 3. iOS: first release + +1. On developer.apple.com, open Identifiers and register the App ID + `com.metatroncubesolutions.nangaKathai`. In-App Purchase is on by default. Background audio + needs nothing extra. +2. In App Store Connect, create the app with the name **Nanga Kathai**, that bundle ID, and primary language English (India or UK). +3. In Codemagic, start the **iOS release (TestFlight)** workflow, or push a tag: + `git tag v1.0.0 && git push github v1.0.0`. + The build is uploaded to TestFlight automatically after about 20–30 minutes plus Apple processing. +4. Test it from the TestFlight app on an iPhone. +5. Fill in the listing (section 5) and submit for review. + +## 4. Android: first release + +1. In Play Console, create the app: Nanga Kathai, App, Free. +2. Build the first bundle locally and upload it manually. Google requires the very first upload to be done by hand. + ``` + flutter build appbundle --release --dart-define-from-file=env.json + ``` + The file is `build/app/outputs/bundle/release/app-release.aab`. Upload it under Testing > + Internal testing > Create release. Accept **Play App Signing**: Google keeps the app signing key, + and you sign uploads with `nk-upload.jks`. +3. Later builds come from the Codemagic **Android release** workflow, which uploads a draft to Internal testing. +4. Promote it from Internal testing, to Closed testing (optional), to Production. + +## 5. Store listing checklist + +**Links (publish the files from `site/` on nkbmusic.com first)** +- Privacy Policy: `https://nkbmusic.com/privacy` +- Terms: `https://nkbmusic.com/terms` +- Account deletion (required by Play): `https://nkbmusic.com/delete-account` +- Support: `support@nkbmusic.com` + +**Graphics** (in `assets/brand/`: `app_icon_1024.png` and `play_store_icon_512.png`) +- Play: a 512×512 icon, a 1024×500 feature graphic, and 2–8 phone screenshots. +- App Store: 6.9-inch iPhone screenshots (1320×2868). The app is iPhone-only, so no iPad screenshots are needed. + +**Questionnaires** +- **Data collected** (Play Data safety and Apple App Privacy): + - email, name, optional phone and photo; + - app interactions (plays) and crash/diagnostics data if crash reporting is added; + - not used for tracking or ads, data encrypted in transit, users can request deletion. +- **Content rating:** music app, no violence and no user chat. Expect *Everyone* / *4+*. +- **Ads:** none. **In-app purchases:** yes (the Support products in `docs/support-payments.md`). + +**App Review notes (important)** +- Create a reviewer account (for example `review@nkbmusic.com`) with a password, and enter it as the sign-in details. Apple and Google can't receive the email code. +- **Music rights** are the most likely reason for a rejection (Apple guideline 5.2.3 and Google's IP + policy). Explain it in the notes: *"Nanga Kathai preserves Badaga community music from a family + collection. Every song has an in-app 'Is this your song?' claim or removal option, and we act on + requests promptly. New songs will come only from verified creators who confirm their rights."* + Keep written permission from any singers you can reach, in case review asks. + +## 6. Keys: back these up now + +`C:\Users\manes\nk-keys\` holds the Android upload key and its password. Copy that folder to +two safe places, such as a password manager and an offline drive. If it is lost, Google can reset +the upload key, but that takes a support request and several days. Never commit it to git. diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 97e73e3..ffa9fcd 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -365,7 +365,7 @@ SDKROOT = iphoneos; STRING_CATALOG_GENERATE_SYMBOLS = YES; SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VALIDATE_PRODUCT = YES; }; name = Profile; @@ -492,7 +492,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; STRING_CATALOG_GENERATE_SYMBOLS = YES; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; }; name = Debug; }; @@ -546,7 +546,7 @@ SUPPORTED_PLATFORMS = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index dc9ada4..5f8d479 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 7353c41..db60832 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 797d452..6d796be 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 6ed2d93..f124c02 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 4cd7b00..db9e649 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index fe73094..3324e62 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 321773c..b3d4b76 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 797d452..6d796be 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 502f463..d5618b6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 0ec3034..2a64a90 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 0ec3034..2a64a90 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index e9f5fea..734a923 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 84ac32a..4ee2f37 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 8953cba..a8982a7 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 0467bf1..8e8f079 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard index f2e259c..af5e818 100644 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -19,7 +19,7 @@ - + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 6fe4925..f33bc39 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -15,7 +15,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - nanga_kathai + Nanga Kathai CFBundlePackageType APPL CFBundleShortVersionString @@ -24,6 +24,17 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + ITSAppUsesNonExemptEncryption + + NSPhotoLibraryUsageDescription + Choose a photo for your Nanga Kathai profile. + NSCameraUsageDescription + Take a photo for your Nanga Kathai profile. + LSApplicationQueriesSchemes + + mailto + https + LSRequiresIPhoneOS UIApplicationSceneManifest @@ -60,8 +71,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/lib/features/settings/document_screen.dart b/lib/features/settings/document_screen.dart index 6035df9..da8f616 100644 --- a/lib/features/settings/document_screen.dart +++ b/lib/features/settings/document_screen.dart @@ -74,7 +74,7 @@ class DocumentScreen extends StatelessWidget { /// **bold** and tappable email addresses. static TextSpan _inline(String s, TextStyle? base) { final spans = []; - final pattern = RegExp(r'\*\*(.+?)\*\*|([\w.+-]+@[\w-]+\.[\w.]+)'); + final pattern = RegExp(r'\*\*(.+?)\*\*|([\w.+-]+@[\w-]+(?:\.[\w-]+)+)'); var last = 0; for (final m in pattern.allMatches(s)) { if (m.start > last) spans.add(TextSpan(text: s.substring(last, m.start))); diff --git a/lib/main.dart b/lib/main.dart index e837982..47bfdc1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -17,6 +18,7 @@ import 'offline/download_store.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); + await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); if (Env.hasSupabase) { await Supabase.initialize(url: Env.supabaseUrl, publishableKey: Env.supabasePublishableKey); diff --git a/site/delete-account.html b/site/delete-account.html new file mode 100644 index 0000000..286e116 --- /dev/null +++ b/site/delete-account.html @@ -0,0 +1,21 @@ + + +Delete your account | Nanga Kathai + +
Nanga Kathai +

Delete your Nanga Kathai account

+

You can delete your Nanga Kathai account, made by Metatroncube Software Solutions, at any time.

+

In the app

+
  1. Open Nanga Kathai and tap the person icon on Home or in Library.
  2. Scroll down and tap Delete account.
  3. Confirm. Your account is deleted straight away.
+

Without the app

+

Email support@nkbmusic.com from the address you signed up with and ask us to delete your account. We will confirm within 7 days.

+

What is deleted

+
  • Your account, email address and password.
  • Your profile: name, photo, village and phone number.
  • Your likes, playlists and listening history on our servers.
+

Copies in our backups are overwritten within about 14 days. Song reports or rights requests you sent may be kept, without your account details, where we need a record of them. Songs you downloaded stay encrypted on your phone until you remove the app.

+

See our Privacy Policy for more.

+
diff --git a/site/privacy.html b/site/privacy.html index 17d96a7..c4653f4 100644 --- a/site/privacy.html +++ b/site/privacy.html @@ -30,7 +30,7 @@ strong{color:#FBF7EE} a{color:#F5B335} li{margin:4px 0} .brand{color:#F5B335;fon

How long we keep it

We keep your account details for as long as your account exists. When you delete your account, your profile, likes, playlists and history on our servers are removed. Backups are overwritten within about 14 days. Reports you sent may be kept, without your account, where we need a record of a rights or removal request.

Your choices and rights

-
  • See and edit your profile in the app (Library > your profile).
  • Delete your account from your profile page. This cannot be undone.
  • Ask us for a copy of your data, a correction, or anything else about your privacy by writing to support@nkbmusic.com.
+
  • See and edit your profile in the app (Library > your profile).
  • Delete your account from your profile page. This cannot be undone.
  • Ask us for a copy of your data, a correction, or anything else about your privacy by writing to support@nkbmusic.com.

These rights apply wherever you live, including your rights under India's Digital Personal Data Protection Act, 2023.

Children

Nanga Kathai is meant for listeners of all ages, but accounts are intended for people aged 18 and over. Younger listeners should use the app with the consent and supervision of a parent or guardian.

diff --git a/site/terms.html b/site/terms.html index e596351..81bd4de 100644 --- a/site/terms.html +++ b/site/terms.html @@ -18,7 +18,7 @@ strong{color:#FBF7EE} a{color:#F5B335} li{margin:4px 0} .brand{color:#F5B335;fon

Our older recordings

Our first songs come from a family collection gathered over many years, and not every artist has been identified yet. We respect the people behind these songs. If you are an artist, rights holder or family member, you can, at any time:

  • claim a song so we credit you correctly,
  • ask us to correct its details, or
  • ask us to remove it.
-

Use "Is this your song?" on the song in the app, or write to support@nkbmusic.com. We review every request and act on genuine removal requests promptly.

+

Use "Is this your song?" on the song in the app, or write to support@nkbmusic.com. We review every request and act on genuine removal requests promptly.

Creators

In a future update, singers, lyricists and music directors will be able to apply to become verified creators. Verification will be manual and may require identity documents. Creators who upload songs will confirm that they own them or have permission from everyone with rights in them, and will accept separate creator terms. Any way for listeners to support creators with money, and any fee we keep, will be set out in those terms before it begins.

Supporting Nanga Kathai

diff --git a/tools/legal_to_html.py b/tools/legal_to_html.py index 6893f79..b2954ab 100644 --- a/tools/legal_to_html.py +++ b/tools/legal_to_html.py @@ -24,7 +24,7 @@ strong{{color:#FBF7EE}} a{{color:#F5B335}} li{{margin:4px 0}} .brand{{color:#F5B def inline(s): s = html.escape(s) s = re.sub(r"\*\*(.+?)\*\*", r"\1", s) - return re.sub(r"([\w.+-]+@[\w-]+\.[\w.]+)", r'\1', s) + return re.sub(r"([\w.+-]+@[\w-]+(?:\.[\w-]+)+)", r'\1', s) def convert(md):