Skip to content

Commit 4a49bdc

Browse files
committed
Connected Telegram-channel fork updates to UpdateAppAlertDialog popup.
1 parent f8b9e76 commit 4a49bdc

5 files changed

Lines changed: 460 additions & 179 deletions

File tree

TMessagesProj/src/main/java/org/telegram/messenger/forkgram/AppUpdater.kt

Lines changed: 35 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,9 @@ import android.widget.Toast
1010
import org.json.JSONObject
1111
import org.json.JSONArray
1212

13-
import android.content.Intent
14-
import android.net.Uri
1513
import android.os.Build
16-
import androidx.core.content.FileProvider
1714
import org.telegram.messenger.AndroidUtilities
1815
import org.telegram.messenger.BuildVars
19-
import org.telegram.messenger.DownloadController
20-
import org.telegram.messenger.FileLoader
2116
import org.telegram.messenger.LocaleController
2217
import org.telegram.messenger.MessagesController
2318
import org.telegram.messenger.UserConfig
@@ -81,7 +76,8 @@ object AppUpdater {
8176
fun checkNewVersion(
8277
parentActivity: Activity,
8378
context: Context,
84-
callback: (AlertDialog.Builder?) -> Int,
79+
legacyCallback: (AlertDialog.Builder?) -> Int,
80+
modernCallback: (TLRPC.TL_help_appUpdate?) -> Int,
8581
manual: Boolean = false) {
8682

8783
try {
@@ -96,10 +92,10 @@ object AppUpdater {
9692

9793
// Try Telegram channel first if we have an active session
9894
if (UserConfig.getInstance(UserConfig.selectedAccount).isClientActivated()) {
99-
checkUpdateFromTelegramChannel(parentActivity, context, callback, manual, currentVersion)
95+
checkUpdateFromTelegramChannel(parentActivity, context, legacyCallback, modernCallback, manual, currentVersion)
10096
} else {
10197
// Fallback to GitHub API
102-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
98+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
10399
}
104100
} catch (e: Exception) {
105101
android.util.Log.e("Fork Client", "Error in checkNewVersion", e)
@@ -112,7 +108,8 @@ object AppUpdater {
112108
private fun checkUpdateFromTelegramChannel(
113109
parentActivity: Activity,
114110
context: Context,
115-
callback: (AlertDialog.Builder?) -> Int,
111+
legacyCallback: (AlertDialog.Builder?) -> Int,
112+
modernCallback: (TLRPC.TL_help_appUpdate?) -> Int,
116113
manual: Boolean,
117114
currentVersion: String) {
118115

@@ -122,14 +119,14 @@ object AppUpdater {
122119
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req) { response, error ->
123120
if (error != null || response !is TLRPC.TL_contacts_resolvedPeer) {
124121
android.util.Log.w("Fork Client", "Failed to resolve update channel, falling back to GitHub")
125-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
122+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
126123
return@sendRequest
127124
}
128125

129126
val chat = response.chats.firstOrNull()
130127
if (chat == null) {
131128
android.util.Log.w("Fork Client", "Update channel not found, falling back to GitHub")
132-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
129+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
133130
return@sendRequest
134131
}
135132

@@ -143,14 +140,14 @@ object AppUpdater {
143140
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(messagesReq) { historyResponse, historyError ->
144141
if (historyError != null || historyResponse !is TLRPC.messages_Messages) {
145142
android.util.Log.w("Fork Client", "Failed to get channel history, falling back to GitHub")
146-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
143+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
147144
return@sendRequest
148145
}
149146

150147
val message = historyResponse.messages.firstOrNull()
151148
if (message?.message == null) {
152149
android.util.Log.w("Fork Client", "No messages in update channel, falling back to GitHub")
153-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
150+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
154151
return@sendRequest
155152
}
156153

@@ -160,7 +157,7 @@ object AppUpdater {
160157
val androidInfo = updateInfo.optJSONObject("android")
161158
if (androidInfo == null) {
162159
android.util.Log.w("Fork Client", "Invalid update JSON format, falling back to GitHub")
163-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
160+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
164161
return@sendRequest
165162
}
166163

@@ -174,14 +171,14 @@ object AppUpdater {
174171

175172
if (releaseInfo.isEmpty()) {
176173
android.util.Log.w("Fork Client", "No version info found, falling back to GitHub")
177-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
174+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
178175
return@sendRequest
179176
}
180177

181178
val parts = releaseInfo.split(":")
182179
if (parts.size != 2) {
183180
android.util.Log.w("Fork Client", "Invalid version format, falling back to GitHub")
184-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
181+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
185182
return@sendRequest
186183
}
187184

@@ -190,7 +187,7 @@ object AppUpdater {
190187

191188
if (fileInfo.size != 2) {
192189
android.util.Log.w("Fork Client", "Invalid file info format, falling back to GitHub")
193-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
190+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
194191
return@sendRequest
195192
}
196193

@@ -199,7 +196,7 @@ object AppUpdater {
199196

200197
if (messageId == null) {
201198
android.util.Log.w("Fork Client", "Invalid message ID, falling back to GitHub")
202-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
199+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
203200
return@sendRequest
204201
}
205202

@@ -215,11 +212,11 @@ object AppUpdater {
215212
}
216213

217214
// Get download URL from files channel
218-
getDownloadUrlFromFilesChannel(parentActivity, context, callback, newVersion, filesChannelUsername, messageId)
215+
getDownloadUrlFromFilesChannel(parentActivity, context, modernCallback, newVersion, filesChannelUsername, messageId)
219216

220217
} catch (e: Exception) {
221218
android.util.Log.e("Fork Client", "Error parsing update info from Telegram, falling back to GitHub", e)
222-
checkUpdateFromGitHub(parentActivity, context, callback, manual, currentVersion)
219+
checkUpdateFromGitHub(parentActivity, context, legacyCallback, manual, currentVersion)
223220
}
224221
}
225222
}
@@ -228,7 +225,7 @@ object AppUpdater {
228225
private fun getDownloadUrlFromFilesChannel(
229226
parentActivity: Activity,
230227
context: Context,
231-
callback: (AlertDialog.Builder?) -> Int,
228+
modernCallback: (TLRPC.TL_help_appUpdate?) -> Int,
232229
newVersion: String,
233230
filesChannelUsername: String,
234231
messageId: Int) {
@@ -269,174 +266,33 @@ object AppUpdater {
269266
return@sendRequest
270267
}
271268

272-
AndroidUtilities.runOnUIThread {
273-
val fullMessage = fileMessage?.message ?: ""
274-
val changelog = if (fullMessage.contains("Changelog:")) {
275-
fullMessage.substringAfter("Changelog:").trim()
276-
} else {
277-
fullMessage.takeIf { it.isNotEmpty() } ?: "A new version is available."
278-
}
279-
val builder = AlertDialog.Builder(parentActivity)
280-
builder.setTitle("New version $newVersion")
281-
builder.setMessage(changelog)
282-
builder.setMessageTextViewClickable(false)
283-
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null)
284-
builder.setPositiveButton("Install") { _, _ ->
285-
val readReq = TLRPC.TL_channels_readHistory()
286-
readReq.channel = inputChannel
287-
readReq.max_id = messageId
288-
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(readReq) { _, _ -> }
289-
290-
try {
291-
val fileName = "$title-$newVersion.apk"
292-
val externalDir = context.getExternalFilesDir(null)
293-
val downloadDir = File(externalDir, android.os.Environment.DIRECTORY_DOWNLOADS)
294-
if (!downloadDir.exists()) {
295-
downloadDir.mkdirs()
296-
}
297-
val destFile = File(downloadDir, fileName)
298-
299-
// Check if file is already downloaded in Telegram cache
300-
val fileLoader = FileLoader.getInstance(UserConfig.selectedAccount)
301-
val cachedPath = fileLoader.getPathToAttach(document, true)
302-
303-
if (cachedPath != null && cachedPath.exists()) {
304-
// File already downloaded, install directly
305-
Toast.makeText(context, "File already downloaded, installing...", Toast.LENGTH_SHORT).show()
306-
cachedPath.copyTo(destFile, overwrite = true)
307-
installApk(context, destFile)
308-
} else {
309-
// Start download
310-
Toast.makeText(context, "Downloading update...", Toast.LENGTH_SHORT).show()
311-
fileLoader.loadFile(document, fileMessage, FileLoader.PRIORITY_HIGH, 0)
312-
DownloadController.getInstance(UserConfig.selectedAccount).setDocumentHidden(document.id)
313-
314-
// Monitor download progress
315-
monitorTelegramDownload(context, document, destFile, newVersion)
316-
}
317-
} catch (e: Exception) {
318-
android.util.Log.e("Fork Client", "Error starting download", e)
319-
Toast.makeText(context, "Download failed: ${e.message}", Toast.LENGTH_SHORT).show()
320-
}
321-
}
322-
callback(builder)
269+
val fullMessage = fileMessage.message ?: ""
270+
val changelog = if (fullMessage.contains("Changelog:")) {
271+
fullMessage.substringAfter("Changelog:").trim()
272+
} else {
273+
fullMessage.takeIf { it.isNotEmpty() } ?: "A new version is available."
323274
}
324-
}
325-
}
326-
}
327275

328-
private fun installApk(context: Context, apkFile: File) {
329-
try {
330-
val intent = Intent(Intent.ACTION_VIEW)
331-
val apkUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
332-
FileProvider.getUriForFile(context, "${context.packageName}.provider", apkFile)
333-
} else {
334-
Uri.fromFile(apkFile)
335-
}
276+
val update = TLRPC.TL_help_appUpdate()
277+
update.version = newVersion
278+
update.text = changelog
279+
update.entities = ArrayList()
280+
update.document = document
281+
update.url = ""
282+
update.can_not_skip = false
336283

337-
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
338-
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
339-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
340-
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
341-
}
284+
val readReq = TLRPC.TL_channels_readHistory()
285+
readReq.channel = inputChannel
286+
readReq.max_id = messageId
287+
ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(readReq) { _, _ -> }
342288

343-
if (intent.resolveActivity(context.packageManager) != null) {
344-
context.startActivity(intent)
345-
} else {
346-
android.util.Log.e("Fork Client", "No activity to handle APK installation")
347289
AndroidUtilities.runOnUIThread {
348-
Toast.makeText(context, "Cannot install APK automatically", Toast.LENGTH_SHORT).show()
290+
modernCallback(update)
349291
}
350292
}
351-
} catch (e: Exception) {
352-
android.util.Log.e("Fork Client", "Error installing APK", e)
353-
AndroidUtilities.runOnUIThread {
354-
Toast.makeText(context, "Installation error: ${e.message}", Toast.LENGTH_SHORT).show()
355-
}
356293
}
357294
}
358295

359-
private fun monitorTelegramDownload(context: Context, document: TLRPC.Document, destFile: File, version: String) {
360-
Thread {
361-
try {
362-
val fileLoader = FileLoader.getInstance(UserConfig.selectedAccount)
363-
val fileName = FileLoader.getAttachFileName(document)
364-
var checkCount = 0
365-
val maxChecks = 240
366-
var wasLoading = false
367-
var loadingStoppedAt = 0
368-
369-
android.util.Log.d("Fork Client", "Starting download monitor for: $fileName")
370-
android.util.Log.d("Fork Client", "Document ID: ${document.id}, DC: ${document.dc_id}, Size: ${document.size}")
371-
372-
while (checkCount < maxChecks) {
373-
Thread.sleep(500)
374-
checkCount++
375-
376-
val path = fileLoader.getPathToAttach(document, true)
377-
val pathFalse = fileLoader.getPathToAttach(document, false)
378-
val isLoading = fileLoader.isLoadingFile(fileName)
379-
380-
if (isLoading) {
381-
wasLoading = true
382-
loadingStoppedAt = 0
383-
} else if (wasLoading && loadingStoppedAt == 0) {
384-
loadingStoppedAt = checkCount
385-
android.util.Log.d("Fork Client", "Loading stopped at check #$checkCount, waiting for file...")
386-
}
387-
388-
if (checkCount % 10 == 0) {
389-
android.util.Log.d("Fork Client", "Check #$checkCount: isLoading=$isLoading, wasLoading=$wasLoading")
390-
android.util.Log.d("Fork Client", " path(true)=${path?.absolutePath}, exists=${path?.exists()}, size=${path?.length() ?: 0}")
391-
android.util.Log.d("Fork Client", " path(false)=${pathFalse?.absolutePath}, exists=${pathFalse?.exists()}, size=${pathFalse?.length() ?: 0}")
392-
}
393-
394-
val validPath = when {
395-
path != null && path.exists() && path.length() > 0 -> path
396-
pathFalse != null && pathFalse.exists() && pathFalse.length() > 0 -> pathFalse
397-
else -> null
398-
}
399-
400-
if (validPath != null) {
401-
android.util.Log.d("Fork Client", "File downloaded: ${validPath.absolutePath}, size: ${validPath.length()}")
402-
403-
AndroidUtilities.runOnUIThread {
404-
Toast.makeText(context, "Download complete, installing...", Toast.LENGTH_SHORT).show()
405-
}
406-
407-
validPath.copyTo(destFile, overwrite = true)
408-
downloadId = 0L
409-
saveApkPath(context, destFile.absolutePath)
410-
411-
AndroidUtilities.runOnUIThread {
412-
installApk(context, destFile)
413-
}
414-
return@Thread
415-
}
416-
417-
if (loadingStoppedAt > 0 && checkCount - loadingStoppedAt > 40) {
418-
android.util.Log.w("Fork Client", "File not found 20 seconds after download stopped")
419-
android.util.Log.w("Fork Client", "Final check - path(true): ${path?.absolutePath}, path(false): ${pathFalse?.absolutePath}")
420-
AndroidUtilities.runOnUIThread {
421-
Toast.makeText(context, "Download failed", Toast.LENGTH_SHORT).show()
422-
}
423-
return@Thread
424-
}
425-
}
426-
427-
android.util.Log.w("Fork Client", "Download timeout after ${maxChecks * 500}ms")
428-
AndroidUtilities.runOnUIThread {
429-
Toast.makeText(context, "Download timeout", Toast.LENGTH_SHORT).show()
430-
}
431-
} catch (e: Exception) {
432-
android.util.Log.e("Fork Client", "Error monitoring download", e)
433-
AndroidUtilities.runOnUIThread {
434-
Toast.makeText(context, "Download error: ${e.message}", Toast.LENGTH_SHORT).show()
435-
}
436-
}
437-
}.start()
438-
}
439-
440296
private fun checkUpdateFromGitHub(
441297
parentActivity: Activity,
442298
context: Context,

TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5890,9 +5890,16 @@ private List<TLRPC.TL_contact> findContacts(String userName, String userPhone, b
58905890

58915891
private boolean firstAppUpdateCheck = true;
58925892
public void checkAppUpdate(boolean force, Browser.Progress progress) {
5893+
final int accountNum = currentAccount;
58935894
AppUpdater.checkNewVersion(this, getBaseContext(), (builder) -> {
58945895
showAlertDialog(builder);
58955896
return 0;
5897+
}, (update) -> {
5898+
if (update == null) {
5899+
return 0;
5900+
}
5901+
ApplicationLoader.applicationLoaderInstance.showUpdateAppPopup(LaunchActivity.this, update, accountNum);
5902+
return 0;
58965903
}, force);
58975904
}
58985905

TMessagesProj_App/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ configurations.all {
2222

2323
dependencies {
2424
implementation project(':TMessagesProj')
25+
implementation 'androidx.fragment:fragment:1.8.9'
26+
implementation 'androidx.core:core:1.16.0'
2527
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
2628
}
2729

0 commit comments

Comments
 (0)