Fix story downloads and update repository URLs

- Skip overlay merging for all story types (public stories, friend stories, spotlight)
- Update all repository URLs from GitHub to Gitea instance
- Update .gitignore to exclude build artifacts and compiled outputs
- Configure updater to sync with new XSnap repository
This commit is contained in:
Mario Duran
2026-02-28 12:26:00 +01:00
parent bc252ea9a3
commit 792a20ae9a
9 changed files with 97 additions and 22 deletions

61
.gitignore vendored
View File

@@ -18,3 +18,64 @@ cloudflare/**/allowed_codes.local.*
security/allowed-codes.local.* security/allowed-codes.local.*
security/allowed_codes.local.* security/allowed_codes.local.*
valdi/node_modules/ valdi/node_modules/
# Android build outputs
*.apk
*.ap_
*.aab
*.dex
*.class
# Generated files
bin/
gen/
out/
release/
# Gradle files
.gradle/
build/
*/build/
# Local configuration file (sdk path, etc)
local.properties
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# Keystore files
*.jks
*.keystore
# External native build folder generated by CMake
.externalNativeBuild
.cxx/
# Version control
.svn/
# IntelliJ
*.ipr
*.iws
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/jarRepositories.xml
.idea/caches
.idea/modules.xml
.idea/.name
.idea/compiler.xml
.idea/misc.xml
# OS-specific files
.DS_Store
Thumbs.db

View File

@@ -1,7 +1,7 @@
<div align="center"> <div align="center">
<div align="center"> <div align="center">
<img src="https://github.com/particle-box/PurrfectSnap/blob/dev/banner.jpg" alt="PurrfectSnap" width="100%"/> <img src="https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/banner.jpg" alt="PurrfectSnap" width="100%"/>
</div> </div>
@@ -12,9 +12,9 @@
<br> <br>
[![Release](https://img.shields.io/github/v/release/particle-box/PurrfectSnap?include_prereleases&style=for-the-badge&color=cba6f7&labelColor=1e1e2e)](https://github.com/particle-box/PurrfectSnap/releases/latest) [![Release](https://img.shields.io/badge/Release-Latest-cba6f7?style=for-the-badge&labelColor=1e1e2e)](https://gitea.majjoduran.app/majjo/XSnap/releases/latest)
[![Downloads](https://img.shields.io/github/downloads/particle-box/PurrfectSnap/total?style=for-the-badge&color=f5bde6&labelColor=1e1e2e)](https://github.com/particle-box/PurrfectSnap/releases) [![Downloads](https://img.shields.io/badge/Downloads-Gitea-f5bde6?style=for-the-badge&labelColor=1e1e2e)](https://gitea.majjoduran.app/majjo/XSnap/releases)
[![License](https://img.shields.io/badge/License-GPL_3.0-f5a97f?style=for-the-badge&labelColor=1e1e2e)](https://github.com/particle-box/PurrfectSnap/blob/dev/LICENSE) [![License](https://img.shields.io/badge/License-GPL_3.0-f5a97f?style=for-the-badge&labelColor=1e1e2e)](https://gitea.majjoduran.app/majjo/XSnap/src/branch/dev/LICENSE)
[Installation](#installation) • [Features](#features) • [Build](#build-from-source) • [Community](#community) [Installation](#installation) • [Features](#features) • [Build](#build-from-source) • [Community](#community)
@@ -223,7 +223,7 @@ Extensibility through custom scripts.
## Installation ## Installation
The guide is no longer needed! The guide is no longer needed!
Just download and install PurrfectSnap from [here](https://github.com/particle-box/PurrfectSnap/releases). The app automatically detects your device type and applies the appropriate setup. Just download and install PurrfectSnap from [here](https://gitea.majjoduran.app/majjo/XSnap/releases). The app automatically detects your device type and applies the appropriate setup.
<br> <br>

View File

@@ -281,7 +281,7 @@ class RemoteSideContext(
.setRequiredNetworkType(NetworkType.CONNECTED) .setRequiredNetworkType(NetworkType.CONNECTED)
.build() .build()
val inputData = Data.Builder() val inputData = Data.Builder()
.putString("announcements_url", "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/announcements.txt") .putString("announcements_url", "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/announcements.txt")
.putString("channel_name", "Announcements") .putString("channel_name", "Announcements")
.putString("channel_description", "Notifications for PurrfectSnap announcements") .putString("channel_description", "Notifications for PurrfectSnap announcements")
.putString("notification_title", "New announcement available") .putString("notification_title", "New announcement available")

View File

@@ -36,7 +36,7 @@ object Updater {
} }
private fun fetchLatestRelease(channel: Channel) = runCatching { private fun fetchLatestRelease(channel: Channel) = runCatching {
val endpoint = Request.Builder().url("https://api.github.com/repos/particle-box/PurrfectSnap/releases").build() val endpoint = Request.Builder().url("https://gitea.majjoduran.app/api/v1/repos/majjo/XSnap/releases").build()
val response = OkHttpClient().newCall(endpoint).execute() val response = OkHttpClient().newCall(endpoint).execute()
if (!response.isSuccessful) throw Throwable("Failed to fetch releases: ${response.code}") if (!response.isSuccessful) throw Throwable("Failed to fetch releases: ${response.code}")
@@ -87,7 +87,7 @@ object Updater {
}.getOrNull() }.getOrNull()
private fun fetchLatestDebugCI() = runCatching { private fun fetchLatestDebugCI() = runCatching {
val actionRuns = OkHttpClient().newCall(Request.Builder().url("https://api.github.com/repos/particle-box/PurrfectSnap/actions/runs?event=workflow_dispatch&branch=dev").build()).execute().use { val actionRuns = OkHttpClient().newCall(Request.Builder().url("https://gitea.majjoduran.app/api/v1/repos/majjo/XSnap/actions/runs?event=workflow_dispatch&branch=dev").build()).execute().use {
if (!it.isSuccessful) throw Throwable("Failed to fetch CI runs: ${it.code}") if (!it.isSuccessful) throw Throwable("Failed to fetch CI runs: ${it.code}")
JsonParser.parseString(it.body?.string()).asJsonObject JsonParser.parseString(it.body?.string()).asJsonObject
} }

View File

@@ -238,7 +238,7 @@ class HomeAbout : Routes.Route() {
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
onClick = { onClick = {
context.androidContext.openLink( context.androidContext.openLink(
"https://github.com/particle-box/PurrfectSnap", "https://gitea.majjoduran.app/majjo/XSnap",
context.translation["toast_open_link_failed"] context.translation["toast_open_link_failed"]
) )
}, },

View File

@@ -149,9 +149,9 @@ class HomeRootSection : Routes.Route() {
} }
private val changelogClient by lazy { OkHttpClient() } private val changelogClient by lazy { OkHttpClient() }
private val changelogStableUrl = "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/changelogs-stable.txt" private val changelogStableUrl = "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/changelogs-stable.txt"
private val changelogPrereleaseUrl = "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/changelogs-prerelease.txt" private val changelogPrereleaseUrl = "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/changelogs-prerelease.txt"
private val announcementsUrl = "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/announcements.txt" private val announcementsUrl = "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/announcements.txt"
private val heroGradientColors = listOf( private val heroGradientColors = listOf(
Color(0xFF5C4B99), Color(0xFF5C4B99),
@@ -808,7 +808,7 @@ class HomeRootSection : Routes.Route() {
).show() ).show()
} else { } else {
val artifactName = "purrfectsnap-${abiName}-debug" val artifactName = "purrfectsnap-${abiName}-debug"
val downloadUrl = "https://nightly.link/particle-box/PurrfectSnap/actions/runs/${latest.workflowId}/$artifactName.zip" val downloadUrl = "https://gitea.majjoduran.app/majjo/XSnap/actions/runs/${latest.workflowId}/$artifactName.zip"
context.log.info("Debug update -> downloading $artifactName from $downloadUrl", "HomeRoot") context.log.info("Debug update -> downloading $artifactName from $downloadUrl", "HomeRoot")
UpdateDownloader.downloadAndInstall(context, downloadUrl, "$artifactName.zip", coroutineScope) UpdateDownloader.downloadAndInstall(context, downloadUrl, "$artifactName.zip", coroutineScope)
} }
@@ -984,7 +984,7 @@ class HomeRootSection : Routes.Route() {
}, },
onGithubClick = { onGithubClick = {
context.androidContext.openLink( context.androidContext.openLink(
"https://github.com/particle-box/PurrfectSnap", "https://gitea.majjoduran.app/majjo/XSnap",
context.translation["toast_open_link_failed"] context.translation["toast_open_link_failed"]
) )
}, },

View File

@@ -183,7 +183,7 @@ fun ScriptCatalog(root: ScriptingRootSection) {
Button( Button(
onClick = { onClick = {
context.androidContext.openLink( context.androidContext.openLink(
"https://github.com/particle-box/PurrfectSnap/blob/dev/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptRepos.md", "https://gitea.majjoduran.app/majjo/XSnap/src/branch/dev/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptRepos.md",
context.translation["toast_open_link_failed"] context.translation["toast_open_link_failed"]
) )
}, },

View File

@@ -89,7 +89,7 @@ class PurrfectSnap {
buildString { buildString {
append("Snapchat timed out while trying to connect to PurrfectSnap\n\n") append("Snapchat timed out while trying to connect to PurrfectSnap\n\n")
append("Make sure you:\n") append("Make sure you:\n")
append(" - Have installed the latest PurrfectSnap version (https://github.com/particle-box/PurrfectSnap)\n") append(" - Have installed the latest PurrfectSnap version (https://gitea.majjoduran.app/majjo/XSnap)\n")
append(" - Disabled battery optimizations\n") append(" - Disabled battery optimizations\n")
append(" - Excluded PurrfectSnap and Snapchat in HideMyApplist") append(" - Excluded PurrfectSnap and Snapchat in HideMyApplist")
}, },

View File

@@ -215,7 +215,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
private fun downloadOperaMedia( private fun downloadOperaMedia(
downloadManagerClient: DownloadManagerClient, downloadManagerClient: DownloadManagerClient,
mediaInfoMap: Map<SplitMediaAssetType, MediaInfo>, mediaInfoMap: Map<SplitMediaAssetType, MediaInfo>,
paramMap: ParamMap paramMap: ParamMap,
downloadSource: MediaDownloadSource
) { ) {
if (mediaInfoMap.isEmpty()) return if (mediaInfoMap.isEmpty()) return
@@ -237,8 +238,19 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
val originalMediaInfo = mediaInfoMap[SplitMediaAssetType.ORIGINAL]!! val originalMediaInfo = mediaInfoMap[SplitMediaAssetType.ORIGINAL]!!
val originalMediaInfoReference = handleLocalReferences(originalMediaInfo.uri) val originalMediaInfoReference = handleLocalReferences(originalMediaInfo.uri)
// Overlay (if present) // Overlay (if present) - skip overlay for all stories
mediaInfoMap[SplitMediaAssetType.OVERLAY]?.let { overlay -> mediaInfoMap[SplitMediaAssetType.OVERLAY]?.let { overlay ->
// Skip overlay merging for all story types
if (downloadSource == MediaDownloadSource.PUBLIC_STORY ||
downloadSource == MediaDownloadSource.STORY ||
downloadSource == MediaDownloadSource.SPOTLIGHT) {
downloadManagerClient.downloadSingleMedia(
originalMediaInfoReference,
DownloadMediaType.fromUri(Uri.parse(originalMediaInfoReference)),
originalMediaInfo.encryption?.toKeyPair()
)
return
}
val overlayReference = handleLocalReferences(overlay.uri) val overlayReference = handleLocalReferences(overlay.uri)
downloadManagerClient.downloadMediaWithOverlay( downloadManagerClient.downloadMediaWithOverlay(
@@ -311,7 +323,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
forceAllowDuplicate = forceAllowDuplicate forceAllowDuplicate = forceAllowDuplicate
), ),
mediaInfoMap, mediaInfoMap,
paramMap paramMap,
MediaDownloadSource.CHAT_MEDIA
) )
return return
} }
@@ -360,7 +373,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
forceAllowDuplicate = forceAllowDuplicate forceAllowDuplicate = forceAllowDuplicate
), ),
mediaInfoMap, mediaInfoMap,
paramMap paramMap,
MediaDownloadSource.STORY
) )
return return
} }
@@ -376,7 +390,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
mediaAuthor = paramMap["CREATOR_DISPLAY_NAME"].toString(), mediaAuthor = paramMap["CREATOR_DISPLAY_NAME"].toString(),
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(), creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate, forceAllowDuplicate = forceAllowDuplicate,
), mediaInfoMap, paramMap) ), mediaInfoMap, paramMap, MediaDownloadSource.SPOTLIGHT)
return return
} }
@@ -506,7 +520,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
downloadSource = MediaDownloadSource.PUBLIC_STORY, downloadSource = MediaDownloadSource.PUBLIC_STORY,
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(), creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate, forceAllowDuplicate = forceAllowDuplicate,
), mediaInfoMap, paramMap) ), mediaInfoMap, paramMap, MediaDownloadSource.PUBLIC_STORY)
} }
private fun shouldAutoDownload(keyFilter: String? = null): Boolean { private fun shouldAutoDownload(keyFilter: String? = null): Boolean {