Polish navigation, Quran flows, and sharing UX

This commit is contained in:
Dwindi Ramadhana
2026-03-18 00:07:10 +07:00
parent a049129a35
commit 2d09b5b356
59 changed files with 11835 additions and 3184 deletions

View File

@@ -13,6 +13,15 @@ val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
val hasReleaseKeystore = listOf(
"keyAlias",
"keyPassword",
"storeFile",
"storePassword",
).all { key ->
val value = keystoreProperties[key] as String?
!value.isNullOrBlank()
}
android {
namespace = "com.jamshalat.diary"
@@ -30,12 +39,14 @@ android {
}
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String?
storeType = "PKCS12"
if (hasReleaseKeystore) {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String?
keyPassword = keystoreProperties["keyPassword"] as String?
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
storePassword = keystoreProperties["storePassword"] as String?
storeType = "PKCS12"
}
}
}
@@ -52,9 +63,13 @@ android {
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("release")
// Use release keystore if configured, otherwise fallback to debug
// signing so local release APK builds remain possible.
signingConfig = if (hasReleaseKeystore) {
signingConfigs.getByName("release")
} else {
signingConfigs.getByName("debug")
}
}
}
}

View File

@@ -2,6 +2,11 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<application
android:label="Jamshalat Diary"
android:name="${applicationName}"
@@ -33,6 +38,21 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<service
android:name="com.ryanheise.audioservice.AudioService"
android:exported="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<receiver
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and

View File

@@ -65,6 +65,11 @@ public final class GeneratedPluginRegistrant {
} catch (Exception e) {
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
}
try {
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.share.SharePlusPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin share_plus, dev.fluttercommunity.plus.share.SharePlusPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.tekartik.sqflite.SqflitePlugin());
} catch (Exception e) {

View File

@@ -1,6 +1,44 @@
package com.jamshalat.diary
import io.flutter.embedding.android.FlutterActivity
import android.hardware.GeomagneticField
import com.ryanheise.audioservice.AudioServiceActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
class MainActivity : AudioServiceActivity() {
companion object {
private const val GEOMAGNETIC_CHANNEL = "com.jamshalat.diary/geomagnetic"
private const val DECLINATION_METHOD = "getDeclination"
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, GEOMAGNETIC_CHANNEL)
.setMethodCallHandler(::handleGeomagneticMethodCall)
}
private fun handleGeomagneticMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method != DECLINATION_METHOD) {
result.notImplemented()
return
}
val latitude = call.argument<Double>("latitude")
val longitude = call.argument<Double>("longitude")
if (latitude == null || longitude == null) {
result.error("INVALID_ARGS", "Latitude and longitude are required.", null)
return
}
val altitude = call.argument<Double>("altitude") ?: 0.0
val timestamp = call.argument<Long>("timestamp") ?: System.currentTimeMillis()
val field = GeomagneticField(
latitude.toFloat(),
longitude.toFloat(),
altitude.toFloat(),
timestamp,
)
result.success(field.declination.toDouble())
}
}