Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 6 additions & 6 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ jobs:
- name: Build libvpx
run: cd presentation/src/main/cpp && ./build.sh

- name: Build Official Libre Debug APK
run: ./gradlew assembleOfficialLibreDebug

- name: Run Official Libre Debug Unit Tests
run: ./gradlew testOfficialLibreDebugUnitTest

# - name: Build Telemt Libre Debug APK
# run: ./gradlew assembleTelemtLibreDebug
#
- name: Build Official Libre Debug APK
run: ./gradlew assembleOfficialLibreDebug

# - name: Run Telemt Libre Debug Unit Tests
# run: ./gradlew testTelemtLibreDebugUnitTest
#
# - name: Build Telemt Libre Debug APK
# run: ./gradlew assembleTelemtLibreDebug
2 changes: 2 additions & 0 deletions app/src/main/java/org/monogram/app/MainContent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.monogram.presentation.features.chats.conversation.ui.StickerSetSheet
import org.monogram.presentation.features.chats.conversation.ui.content.ChatContentViewers
import org.monogram.presentation.features.profile.ProfileViewers
import org.monogram.presentation.features.stickers.core.toDomain
import org.monogram.presentation.features.stories.StoriesHostContent
import org.monogram.presentation.root.RootComponent
import org.monogram.presentation.root.StartupComponent
import org.monogram.presentation.root.StartupContent
Expand Down Expand Up @@ -135,6 +136,7 @@ fun MainContent(
) {
ProxyConfirmSheet(root)
ChatConfirmJoinSheet(root)
StoriesHostContent(root.storiesHost)
}

if (!isStartupActive && startupOverlayComponent != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ class SwipeBackResolverTest {
MutableStateFlow(ChatListComponent.SelectionState())
override val searchState: StateFlow<ChatListComponent.SearchState> =
MutableStateFlow(ChatListComponent.SearchState())
override val storiesState: StateFlow<ChatListComponent.StoriesState> =
MutableStateFlow(ChatListComponent.StoriesState())
override val appPreferences: AppPreferences
get() = throw UnsupportedOperationException("Not used by resolver tests")

Expand Down Expand Up @@ -214,6 +216,11 @@ class SwipeBackResolverTest {
override fun onDismissInstantView() = unsupported()
override fun onOpenWebApp(url: String, botUserId: Long, botName: String) = unsupported()
override fun onDismissWebApp() = unsupported()
override fun onShareToStory(mediaUrl: String, text: String?, widgetLink: String?) =
unsupported()

override fun onStoryClicked(chatId: Long, storyId: Int?) = unsupported()
override fun onAddStoryClicked() = unsupported()
override fun onOpenWebView(url: String) = unsupported()
override fun onDismissWebView() = unsupported()
override fun onUpdateClicked() = unsupported()
Expand Down
27 changes: 15 additions & 12 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ for %%S in (!SOURCES!) do (
if /I "%%R"=="google" set "OUTPUT_FLAVOR=%%SFirebase"
set "OUTPUT_DIR=%SCRIPT_DIR%app\build\outputs\apk\!OUTPUT_FLAVOR!\%%B"

echo Building !VARIANT_LABEL!
echo Gradle task: !TASK!
call "%SCRIPT_DIR%gradlew.bat" !TASK!
set "VERIFY_TASK=verify!SOURCE_CAP!!RUNTIME_CAP!!TYPE_CAP!BeforeAssemble"

echo Verifying tests and building !VARIANT_LABEL!
echo Gradle tasks: !VERIFY_TASK! !TASK!
call "%SCRIPT_DIR%gradlew.bat" !VERIFY_TASK! !TASK!
if errorlevel 1 (
echo Build failed.
goto fail
Expand Down Expand Up @@ -385,16 +387,16 @@ echo TDLib: %SOURCES%
echo Runtime: %RUNTIMES%
echo Build type: %BUILD_TYPES%
echo ABI filter: %ABI_FILTER%
echo Gradle tasks: %TASK_COUNT%
echo Build variants: %TASK_COUNT%
echo.
exit /b 0

:print_usage
echo Usage:
echo build-apk.bat
echo build-apk.bat [filters...]
echo build-apk.bat --help
echo build-apk.bat --list
echo build.bat
echo build.bat [filters...]
echo build.bat --help
echo build.bat --list
echo.
echo Interactive mode:
echo 1. Select TDLib source: official / telemt / both
Expand Down Expand Up @@ -424,15 +426,16 @@ echo -type-all Build debug and release
echo -abi-all Show all generated APKs
echo.
echo Examples:
echo build-apk.bat -o -f -r -a64
echo build-apk.bat -t -g -d
echo build-apk.bat -all-official
echo build-apk.bat -all
echo build.bat -o -f -r -a64
echo build.bat -t -g -d
echo build.bat -all-official
echo build.bat -all
echo.
echo Notes:
echo - If you pass filters, any group you do not specify defaults to "all".
echo - The script validates the Android SDK path before starting Gradle.
echo - Google builds require app\google-services.json.
echo - Unit-test verification runs before each APK assemble task.
echo - ABI selection filters the APK files shown after the build.
echo Gradle still produces the split outputs configured by the project.
exit /b 0
Expand Down
45 changes: 45 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,51 @@ val localProperties by lazy {
}
extra.set("localProperties", localProperties)

val tdlibFlavors = listOf("Official", "Telemt")
val runtimeFlavors = listOf("Firebase", "Libre")
val buildTypes = listOf("Debug", "Release")

data class AppAssemblyVariant(
val tdlib: String,
val runtime: String,
val buildType: String,
) {
val name: String get() = "$tdlib$runtime$buildType"
val unitTestBuildType: String get() = "Debug"
val unitTestVariantName: String get() = "$tdlib$runtime$unitTestBuildType"
}

val appAssemblyVariants =
tdlibFlavors.flatMap { tdlib ->
runtimeFlavors.flatMap { runtime ->
buildTypes.map { buildType ->
AppAssemblyVariant(
tdlib = tdlib,
runtime = runtime,
buildType = buildType,
)
}
}
}

appAssemblyVariants.forEach { variant ->
val verifyTask = tasks.register("verify${variant.name}BeforeAssemble") {
group = "verification"
description = "Runs module unit tests before assembling the ${variant.name} APK."
dependsOn(
":app:test${variant.unitTestVariantName}UnitTest",
":data:test${variant.unitTestVariantName}UnitTest",
":presentation:test${variant.unitTestVariantName}UnitTest",
":core:test",
":domain:test",
)
}

project(":app").tasks.matching { it.name == "assemble${variant.name}" }.configureEach {
dependsOn(verifyTask)
}
}

tasks.register("assembleOfficialReleaseTdlibApks") {
group = "build"
description = "Assembles release APKs with the official TDLib prebuilts."
Expand Down
34 changes: 22 additions & 12 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ HAS_ARGS=0
print_usage() {
cat <<'EOF'
Usage:
./build-apk.sh
./build-apk.sh [filters...]
./build-apk.sh --help
./build-apk.sh --list
./build.sh
./build.sh [filters...]
./build.sh --help
./build.sh --list

Interactive mode:
1. Select TDLib source: official / telemt / both
Expand Down Expand Up @@ -47,15 +47,16 @@ Extra filters:
-abi-all Show all generated APKs

Examples:
./build-apk.sh -o -f -r -a64
./build-apk.sh -t -g -d
./build-apk.sh -all-official
./build-apk.sh -all
./build.sh -o -f -r -a64
./build.sh -t -g -d
./build.sh -all-official
./build.sh -all

Notes:
- If you pass filters, any group you do not specify defaults to "all".
- The script validates the Android SDK path before starting Gradle.
- Google builds require app/google-services.json.
- Unit-test verification runs before each APK assemble task.
- ABI selection filters the APK files shown after the build.
Gradle still produces the split outputs configured by the project.
EOF
Expand Down Expand Up @@ -354,6 +355,14 @@ build_task_for() {
printf ':app:assemble%s%s%s' "$source_value" "$runtime_value" "$build_type_value"
}

verify_task_for() {
source_value=$(source_capitalized "$1")
runtime_value=$(runtime_capitalized "$2")
build_type_value=$(build_type_capitalized "$3")

printf 'verify%s%s%sBeforeAssemble' "$source_value" "$runtime_value" "$build_type_value"
}

variant_label_for() {
printf '%s-%s-%s' "$1" "$2" "$3"
}
Expand Down Expand Up @@ -516,7 +525,7 @@ print_selection_summary() {
echo " Runtime: $runtimes"
echo " Build type: $build_types"
echo " ABI filter: $abi_filter"
echo " Gradle tasks: $task_count"
echo " Build variants: $task_count"
echo
}

Expand Down Expand Up @@ -591,11 +600,12 @@ for source_value in $SOURCES; do
for runtime_value in $RUNTIMES; do
for build_type_value in $BUILD_TYPES; do
task=$(build_task_for "$source_value" "$runtime_value" "$build_type_value")
verify_task=$(verify_task_for "$source_value" "$runtime_value" "$build_type_value")
label=$(variant_label_for "$source_value" "$runtime_value" "$build_type_value")

echo "Building $label"
echo "Gradle task: $task"
"$GRADLEW" "$task"
echo "Verifying tests and building $label"
echo "Gradle tasks: $verify_task $task"
"$GRADLEW" "$verify_task" "$task"
echo

print_artifacts_for_variant "$source_value" "$runtime_value" "$build_type_value" "$ABI_FILTER"
Expand Down
20 changes: 10 additions & 10 deletions data/src/main/java/org/monogram/data/chats/ChatModelFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ChatModelFactory(
private val appPreferences: AppPreferencesProvider,
private val userFullInfoDao: UserFullInfoDao,
private val muteResolver: NotificationMuteResolver = NotificationMuteResolver(),
private val triggerUpdate: (Long?) -> Unit,
private val scheduleUpdate: (Long) -> Unit,
private val fetchUser: (Long) -> Unit
) {
private val missingUserFullInfoUntilMs = ConcurrentHashMap<Long, Long>()
Expand Down Expand Up @@ -95,7 +95,7 @@ class ChatModelFactory(
if (type.basicGroupId == 0L) return@lazyLoad
val result = gateway.execute(TdApi.GetBasicGroup(type.basicGroupId))
cache.basicGroups[result.id] = result
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
}

cache.basicGroupFullInfoCache[type.basicGroupId]?.let { fullInfo ->
Expand All @@ -106,7 +106,7 @@ class ChatModelFactory(
if (type.basicGroupId == 0L) return@lazyLoad
val result = gateway.execute(TdApi.GetBasicGroupFullInfo(type.basicGroupId))
cache.basicGroupFullInfoCache[type.basicGroupId] = result
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
}
}

Expand Down Expand Up @@ -141,7 +141,7 @@ class ChatModelFactory(
if (type.supergroupId == 0L) return@lazyLoad
val result = gateway.execute(TdApi.GetSupergroup(type.supergroupId))
cache.supergroups[result.id] = result
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
}

val canLoadSupergroupFullInfo = supergroup?.status?.let {
Expand All @@ -157,7 +157,7 @@ class ChatModelFactory(
if (type.supergroupId == 0L) return@lazyLoad
val result = gateway.execute(TdApi.GetSupergroupFullInfo(type.supergroupId))
cache.supergroupFullInfoCache[type.supergroupId] = result
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
}
}
}
Expand Down Expand Up @@ -202,7 +202,7 @@ class ChatModelFactory(
lazyLoad(cache.pendingUserFullInfo, type.userId) {
if (type.userId == 0L) return@lazyLoad
cache.userFullInfoCache[type.userId]?.let {
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
return@lazyLoad
}
val cachedInfo = coRunCatching {
Expand All @@ -211,7 +211,7 @@ class ChatModelFactory(
if (cachedInfo != null) {
cache.putUserFullInfo(type.userId, cachedInfo)
missingUserFullInfoUntilMs.remove(type.userId)
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
return@lazyLoad
}
val result = userFullInfoSemaphore.withPermit {
Expand All @@ -223,7 +223,7 @@ class ChatModelFactory(
cache.putUserFullInfo(type.userId, result)
coRunCatching { userFullInfoDao.insertUserFullInfo(result.toEntity(type.userId)) }
missingUserFullInfoUntilMs.remove(type.userId)
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
} else {
rememberMissingUserFullInfo(type.userId)
}
Expand All @@ -240,7 +240,7 @@ class ChatModelFactory(
lazyLoad(cache.pendingChatPermissions, chat.id) {
val result = gateway.execute(TdApi.GetChat(chat.id))
cache.chatPermissionsCache[chat.id] = result.permissions
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
}
}

Expand All @@ -260,7 +260,7 @@ class ChatModelFactory(
TdApi.GetChatMember(chat.id, TdApi.MessageSenderUser(me.id))
)
cache.myChatMemberCache[chat.id] = member
triggerUpdate(chat.id)
scheduleUpdate(chat.id)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ChatUpdateHandler(
private val onSaveChatsBySupergroupId: (Long) -> Unit,
private val onSaveChatsByBasicGroupId: (Long) -> Unit,
private val onTriggerUpdate: (Long?) -> Unit,
private val onScheduleUpdate: (Long?) -> Unit,
private val onRefreshChat: suspend (Long) -> Unit,
private val onRefreshForumTopics: () -> Unit,
private val onAuthorizationStateClosed: () -> Unit
Expand Down Expand Up @@ -163,7 +164,7 @@ class ChatUpdateHandler(
is TdApi.UpdateFile -> {
if (fileManager.handleFileUpdate(update.file)) {
val chatId = fileManager.getChatIdByPhotoId(update.file.id)
onTriggerUpdate(chatId)
onScheduleUpdate(chatId)
onRefreshForumTopics()
}
}
Expand All @@ -183,7 +184,7 @@ class ChatUpdateHandler(
is TdApi.UpdateUserStatus -> {
cache.updateUser(update.userId) { it.status = update.status }
cache.userIdToChatId[update.userId]?.let { chatId ->
onTriggerUpdate(chatId)
onScheduleUpdate(chatId)
}
}

Expand Down Expand Up @@ -281,7 +282,7 @@ class ChatUpdateHandler(
is TdApi.UpdateChatOnlineMemberCount -> {
cache.putOnlineMemberCount(update.chatId, update.onlineMemberCount)
onSaveChat(update.chatId)
onTriggerUpdate(update.chatId)
onScheduleUpdate(update.chatId)
}

is TdApi.UpdateAuthorizationState -> {
Expand Down
Loading