Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
0eca356
refactor(data): replace ScopeProvider with CoroutineScope and remove …
gdlbo Apr 6, 2026
5aca914
Rewritten mappings of chats/messages (#200)
gdlbo Apr 6, 2026
c2fa490
Better mappings + memory logger (#204)
gdlbo Apr 6, 2026
c3bd470
photo: better crop (#188)
aliveoutside Apr 6, 2026
be8d206
feat(photo-editor): add rotate to crop
aliveoutside Apr 6, 2026
aa9d1b8
feat(photo-editor): smoother rotate animation
aliveoutside Apr 6, 2026
18c39ac
better notifications info caching
gdlbo Apr 6, 2026
8cedbad
feat(chat): smoother mic/send button animation
aliveoutside Apr 6, 2026
926514b
fixed runtime update user info in chat
gdlbo Apr 6, 2026
dec286e
thread send message fix + caption message fix
gdlbo Apr 6, 2026
4a8842c
fix #174
gdlbo Apr 6, 2026
162928f
slow mode, mute etc. support
gdlbo Apr 6, 2026
7b42fa0
fix disable drag-to-back in chats
gdlbo Apr 6, 2026
c8469e7
fix chat settings ui
gdlbo Apr 7, 2026
6614dd0
pins redesign + fix #73
gdlbo Apr 7, 2026
8f1937a
rewritten pinned sheet
gdlbo Apr 7, 2026
803460e
remove password length limit (#210)
fimkov Apr 7, 2026
6db2fc1
phone number input screen improvements (#209)
fimkov Apr 7, 2026
a072091
better animations of pins
gdlbo Apr 7, 2026
f05cab9
chore: update project dependencies
gdlbo Apr 7, 2026
11eeca9
fix: rename release APK outputs
gdlbo Apr 7, 2026
ca9c306
fix media download event routing and message cache collisions
gdlbo Apr 7, 2026
7467cae
Remove non-existent `web_app_set_header_text` event and page reload o…
SecondThundeR Apr 8, 2026
eab7b5b
Update sensors handling and move evaluateJavascript to message queue …
SecondThundeR Apr 8, 2026
6178c23
feat: fast reply gesture (#168)
andr0d1v Apr 8, 2026
33c9da5
Add androidx-compose-ui version and update refs
gdlbo Apr 8, 2026
9f8c2b1
Optimize chat UI updates and typing dots
gdlbo Apr 8, 2026
028a12b
Enable configuration cache; simplify build tasks
gdlbo Apr 8, 2026
984e6bc
Preserve string/plurals with keep.xml
gdlbo Apr 8, 2026
37ee6b1
targeted media path updates
gdlbo Apr 8, 2026
714da74
Add video duration to gallery items and UI
gdlbo Apr 8, 2026
e579db9
feat(files): download progress (#215)
andr0d1v Apr 9, 2026
27f3a22
Pretty folding and unfolding, fullscreen media, no hang on startup an…
keimoger Apr 9, 2026
62540fb
fixed profile paddings
gdlbo Apr 9, 2026
2c17f68
optimize file update pipeline and wallpaper persistence
gdlbo Apr 9, 2026
5fa4aee
localize chat and notification UI strings across modules
gdlbo Apr 9, 2026
a45151d
localize sender label in notification quick replies
gdlbo Apr 9, 2026
3e7a874
fix profile top bar badge wrapping on narrow widths
gdlbo Apr 9, 2026
6e175d4
Update TDLib badge to 1.8.63
gdlbo Apr 9, 2026
8d4cfc3
feat: android workflow ci (#218)
andr0d1v Apr 9, 2026
d3862e4
implement Android 12+ SplashScreen API
gdlbo Apr 9, 2026
5c4472e
support saving media albums to downloads
gdlbo Apr 9, 2026
8dcb7c4
update message bubble components and album handling
gdlbo Apr 9, 2026
7219766
update ChatInputBarComposerSection vertical alignment to center
gdlbo Apr 9, 2026
7469151
fix #202
gdlbo Apr 9, 2026
8e20634
update splash screen to support monochrome icons and dynamic colors
gdlbo Apr 9, 2026
cfaf58f
support pasting images from clipboard
gdlbo Apr 9, 2026
ac27462
defer non-critical startup work for faster cold start
gdlbo Apr 9, 2026
6340b9d
optimize chat compose state and list rendering paths
gdlbo Apr 9, 2026
627bd9d
improve chat viewport restoration and scrolling precision
gdlbo Apr 9, 2026
d0fc90c
Start foreground notification before FCM stop
gdlbo Apr 10, 2026
b5fbb54
improve tablet layout, localization, and message rendering
gdlbo Apr 10, 2026
1e98ed5
refine message bubble grouping and sender block logic
gdlbo Apr 10, 2026
709c766
refine chat message options and translation/summary logic
gdlbo Apr 10, 2026
520eb8f
Refactor startup overlay state handling
gdlbo Apr 10, 2026
e9d5db2
replace gallery top bar puzzle icon with photo library
gdlbo Apr 10, 2026
334c3ef
guard scheduled messages fetch by chat rights
gdlbo Apr 10, 2026
998ad66
add copy cut paste actions to fullscreen editor
gdlbo Apr 10, 2026
75e09f1
armv7 crash and performance fix
gdlbo Apr 10, 2026
c687991
add toggle for tablet split-screen interface
gdlbo Apr 10, 2026
3ad52c3
Add 12h format support depending on locale (#219)
iWisp360 Apr 10, 2026
ebd9459
eagerly initialize OfflineWarmup and SponsorSyncManager
gdlbo Apr 10, 2026
755565c
fix message text rendering and prevent substring out-of-bounds crashes
gdlbo Apr 10, 2026
fca9fb2
remove telega proxy integration and settings flow
gdlbo Apr 11, 2026
9de8cae
advanced proxy management and network-specific routing rules
gdlbo Apr 11, 2026
9de90db
rename development build to Alpha across localized strings
gdlbo Apr 11, 2026
d823012
implement separate audio recording and improve transcoding in `Advanc…
gdlbo Apr 11, 2026
9950df7
refine video gesture controls and dismissal logic
gdlbo Apr 11, 2026
1ce5811
bump version to 0.0.7
gdlbo Apr 11, 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
63 changes: 63 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Android CI

on:
pull_request:
branches: ["master", "develop"]
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
submodules: recursive
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
cache: gradle

- name: Make all scripts executable
run: |
chmod +x gradlew
chmod +x presentation/src/main/cpp/build.sh

- name: Build libvpx
run: cd presentation/src/main/cpp && ./build.sh

- name: Build Debug APK (without GMS)
run: ./gradlew assembleDebug

- name: Run Unit Tests
run: ./gradlew testDebugUnitTest

- name: Upload universal APK
uses: actions/upload-artifact@v7
with:
name: app-universal-no-appid
path: app/build/outputs/apk/debug/app-universal-debug.apk

- name: Upload arm64-v8a APK
uses: actions/upload-artifact@v7
with:
name: app-arm64-v8a-no-appid
path: app/build/outputs/apk/debug/app-arm64-v8a-debug.apk

- name: Upload armeabi-v7a APK
uses: actions/upload-artifact@v7
with:
name: app-armeabi-v7a-no-appid
path: app/build/outputs/apk/debug/app-armeabi-v7a-debug.apk

- name: Upload x86_64 APK
uses: actions/upload-artifact@v7
with:
name: app-x86_64-no-appid
path: app/build/outputs/apk/debug/app-x86_64-debug.apk
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<img src="https://img.shields.io/github/stars/monogram-android/monogram" width="120">
</a>
<img src="https://img.shields.io/badge/Kotlin-2.0+-blue.svg?logo=kotlin" width="130">
<img src="https://img.shields.io/badge/TDLib-1.8.62-blue" width="120">
<img src="https://img.shields.io/badge/TDLib-1.8.63-blue" width="120">
<img src="https://img.shields.io/badge/Status-Active_Development-orange" width="170">
<a href="https://boosty.to/monogram">
<img src="https://img.shields.io/badge/Boosty-Support_the_project-ff6f61?logo=boosty&logoColor=white" width="200">
Expand Down
2 changes: 1 addition & 1 deletion README_ES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<img src="https://img.shields.io/github/stars/monogram-android/monogram" width="120">
</a>
<img src="https://img.shields.io/badge/Kotlin-2.0+-blue.svg?logo=kotlin" width="130">
<img src="https://img.shields.io/badge/TDLib-1.8.62-blue" width="120">
<img src="https://img.shields.io/badge/TDLib-1.8.63-blue" width="120">
<img src="https://img.shields.io/badge/Status-Active_Development-orange" width="170">
<a href="https://boosty.to/monogram">
<img src="https://img.shields.io/badge/Boosty-Support_the_project-ff6f61?logo=boosty&logoColor=white" width="200">
Expand Down
2 changes: 1 addition & 1 deletion README_KOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<img src="https://img.shields.io/github/stars/monogram-android/monogram" width="120">
</a>
<img src="https://img.shields.io/badge/Kotlin-2.0+-blue.svg?logo=kotlin" width="130">
<img src="https://img.shields.io/badge/TDLib-1.8.62-blue" width="120">
<img src="https://img.shields.io/badge/TDLib-1.8.63-blue" width="120">
<img src="https://img.shields.io/badge/Status-Active_Development-orange" width="170">
<a href="https://boosty.to/monogram">
<img src="https://img.shields.io/badge/Boosty-Support_the_project-ff6f61?logo=boosty&logoColor=white" width="200">
Expand Down
2 changes: 1 addition & 1 deletion README_RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<img src="https://img.shields.io/github/stars/monogram-android/monogram" width="120">
</a>
<img src="https://img.shields.io/badge/Kotlin-2.0+-blue.svg?logo=kotlin" width="130">
<img src="https://img.shields.io/badge/TDLib-1.8.62-blue" width="120">
<img src="https://img.shields.io/badge/TDLib-1.8.63-blue" width="120">
<img src="https://img.shields.io/badge/Status-Active_Development-orange" width="170">
<a href="https://boosty.to/monogram">
<img src="https://img.shields.io/badge/Boosty-Support_the_project-ff6f61?logo=boosty&logoColor=white" width="200">
Expand Down
2 changes: 1 addition & 1 deletion README_UR.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<img src="https://img.shields.io/github/stars/monogram-android/monogram" width="120">
</a>
<img src="https://img.shields.io/badge/Kotlin-2.0+-blue.svg?logo=kotlin" width="130">
<img src="https://img.shields.io/badge/TDLib-1.8.62-blue" width="120">
<img src="https://img.shields.io/badge/TDLib-1.8.63-blue" width="120">
<img src="https://img.shields.io/badge/Status-Active_Development-orange" width="170">
<a href="https://boosty.to/monogram">
<img src="https://img.shields.io/badge/Boosty-Support_the_project-ff6f61?logo=boosty&logoColor=white" width="200">
Expand Down
90 changes: 52 additions & 38 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import com.android.build.api.artifact.SingleArtifact
import com.android.build.api.variant.FilterConfiguration
import com.android.build.api.variant.impl.VariantOutputImpl
import com.google.android.gms.oss.licenses.plugin.DependencyTask
import com.google.gms.googleservices.GoogleServicesPlugin

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.google.oss.licenses)
alias(libs.plugins.google.services)
Expand All @@ -20,8 +20,8 @@ android {
applicationId = "org.monogram"
minSdk = 25
targetSdk = 36
versionCode = 6
versionName = "0.0.6"
versionCode = 7
versionName = "0.0.7"
}

splits {
Expand All @@ -45,10 +45,16 @@ android {
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
buildFeatures {
resValues = true
}
signingConfig = signingConfigs.getByName("debug")
resValue("string", "app_name", "MonoGram")
}
debug {
buildFeatures {
resValues = true
}
applicationIdSuffix = ".debug"
isMinifyEnabled = false
resValue("string", "app_name", "MonoGram Debug")
Expand All @@ -58,54 +64,56 @@ android {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
kotlin {
jvmToolchain(21)
}
buildFeatures {
compose = true
}
}

androidComponents {
onVariants { variant ->
if (variant.buildType != "release") return@onVariants

variant.outputs.forEach { output ->
val variantOutput = output as? VariantOutputImpl ?: return@forEach
val abi = variantOutput.filters.find {
it.filterType == FilterConfiguration.FilterType.ABI
}?.identifier ?: "universal"
val versionName = variantOutput.versionName.orNull ?: "unknown"

variantOutput.outputFileName.set(
"monogram-$abi-$versionName-${variant.buildType}.apk"
)
}

val apkDirProvider = variant.artifacts.get(SingleArtifact.APK)
val artifactsLoader = variant.artifacts.getBuiltArtifactsLoader()

val renameTask = tasks.register("rename${variant.name.capitalize()}Apk") {
inputs.dir(apkDirProvider)

doLast {
val builtArtifacts = artifactsLoader.load(apkDirProvider.get())!!
val targetDir = apkDirProvider.get().asFile

builtArtifacts.elements.forEach { artifact ->
val abi = artifact.filters.find {
it.filterType == FilterConfiguration.FilterType.ABI
}?.identifier ?: "universal"
val versionName = artifact.versionName
val versionCode = artifact.versionCode
val buildType = variant.buildType

val originalApk = File(artifact.outputFile)
val targetFile = File(
targetDir,
"monogram-$abi-${versionName}(${versionCode})-${buildType}.apk"
)

originalApk.copyTo(targetFile, overwrite = true)
}

val capitalizedVariantName = variant.name.replaceFirstChar {
if (it.isLowerCase()) it.titlecase() else it.toString()
}

val copyTask = tasks.register<Sync>("copy${capitalizedVariantName}Apk") {
from(apkDirProvider)
include("*.apk")
into(layout.projectDirectory.dir("releases"))

doFirst {
destinationDir.mkdirs()
destinationDir.listFiles()
?.filter { it.isFile && it.extension == "apk" && it.name.startsWith("monogram-") }
?.forEach { it.delete() }
}
}

project.tasks.matching { it.name == "assemble${variant.name.capitalize()}" }.configureEach {
finalizedBy(renameTask)
project.tasks.matching { it.name == "assemble${capitalizedVariantName}" }.configureEach {
finalizedBy(copyTask)
}
}
}

dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.bundles.androidx.compose)
implementation(libs.androidx.core.splashscreen)

implementation(libs.bundles.decompose)
implementation(libs.bundles.koin)
Expand All @@ -131,14 +139,20 @@ dependencies {

tasks.withType(DependencyTask::class.java).configureEach {
if (name == "debugOssDependencyTask") {
val releaseTaskProvider = project.tasks.named<DependencyTask>("releaseOssDependencyTask")
val releaseJsonProvider =
layout.buildDirectory.file("generated/third_party_licenses/release/dependencies.json")
val debugJsonProvider =
layout.buildDirectory.file("generated/third_party_licenses/debug/dependencies.json")

dependsOn(releaseTaskProvider)
dependsOn("releaseOssDependencyTask")

doLast {
val releaseJson = releaseTaskProvider.get().dependenciesJson.get().asFile
val debugJson = dependenciesJson.get().asFile
if (releaseJson.exists()) releaseJson.copyTo(debugJson, overwrite = true)
val releaseJson = releaseJsonProvider.get().asFile
val debugJson = debugJsonProvider.get().asFile
if (releaseJson.exists()) {
debugJson.parentFile?.mkdirs()
releaseJson.copyTo(debugJson, overwrite = true)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
android:label="@string/app_name"
android:launchMode="singleTask"
android:supportsPictureInPicture="true"
android:theme="@style/Theme.MonoGram"
android:theme="@style/Theme.MonoGram.Startup"
android:windowSoftInputMode="adjustResize"
tools:targetApi="33">
<intent-filter>
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/java/org/monogram/app/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.koin.core.context.startKoin
import org.maplibre.android.MapLibre
import org.maplibre.android.WellKnownTileServer
import org.monogram.app.di.appModule
import org.monogram.data.infra.DataMemoryPressureHandler
import org.monogram.domain.managers.DistrManager
import org.monogram.domain.repository.AppPreferencesProvider
import org.monogram.domain.repository.PushProvider
Expand All @@ -33,6 +34,19 @@ class App : Application(), SingletonImageLoader.Factory {
checkPushAvailability()
}

@Suppress("DEPRECATION")
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
if (level >= TRIM_MEMORY_RUNNING_LOW) {
trimInMemoryCaches("onTrimMemory:$level")
}
}

override fun onLowMemory() {
super.onLowMemory()
trimInMemoryCaches("onLowMemory")
}

private fun initCrashHandler() {
val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
Expand Down Expand Up @@ -79,7 +93,26 @@ class App : Application(), SingletonImageLoader.Factory {
}
}

private fun trimInMemoryCaches(reason: String) {
if (!::container.isInitialized) return
runCatching {
get<DataMemoryPressureHandler>().clearDataCaches(reason)
}.onFailure { error ->
Log.w(TAG, "Failed to clear data caches for $reason", error)
}

runCatching {
get<ImageLoader>().memoryCache?.clear()
}.onFailure { error ->
Log.w(TAG, "Failed to clear Coil memory cache for $reason", error)
}
}

override fun newImageLoader(context: PlatformContext): ImageLoader {
return get<ImageLoader>()
}

companion object {
private const val TAG = "App"
}
}
Loading