diff --git a/.gitignore b/.gitignore
index 769477b4..36faeac4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,64 @@ cloudflare/**/allowed_codes.local.*
security/allowed-codes.local.*
security/allowed_codes.local.*
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
diff --git a/README.md b/README.md
index c67963a1..01590d67 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-

+
@@ -12,9 +12,9 @@
-[](https://github.com/particle-box/PurrfectSnap/releases/latest)
-[](https://github.com/particle-box/PurrfectSnap/releases)
-[](https://github.com/particle-box/PurrfectSnap/blob/dev/LICENSE)
+[](https://gitea.majjoduran.app/majjo/XSnap/releases/latest)
+[](https://gitea.majjoduran.app/majjo/XSnap/releases)
+[](https://gitea.majjoduran.app/majjo/XSnap/src/branch/dev/LICENSE)
[Installation](#installation) • [Features](#features) • [Build](#build-from-source) • [Community](#community)
@@ -223,7 +223,7 @@ Extensibility through custom scripts.
## Installation
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.
diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt
index 65dc9db2..3ae8558e 100644
--- a/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt
+++ b/app/src/main/kotlin/me/eternal/purrfectsnap/RemoteSideContext.kt
@@ -281,7 +281,7 @@ class RemoteSideContext(
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
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_description", "Notifications for PurrfectSnap announcements")
.putString("notification_title", "New announcement available")
diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt
index 0d498a3d..a60e391e 100644
--- a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt
+++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/data/Updater.kt
@@ -36,7 +36,7 @@ object Updater {
}
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()
if (!response.isSuccessful) throw Throwable("Failed to fetch releases: ${response.code}")
@@ -87,7 +87,7 @@ object Updater {
}.getOrNull()
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}")
JsonParser.parseString(it.body?.string()).asJsonObject
}
diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeAbout.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeAbout.kt
index d1a7949a..a13db81d 100644
--- a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeAbout.kt
+++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeAbout.kt
@@ -238,7 +238,7 @@ class HomeAbout : Routes.Route() {
modifier = Modifier.weight(1f),
onClick = {
context.androidContext.openLink(
- "https://github.com/particle-box/PurrfectSnap",
+ "https://gitea.majjoduran.app/majjo/XSnap",
context.translation["toast_open_link_failed"]
)
},
diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeRootSection.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeRootSection.kt
index 8a84379c..cf879fbb 100644
--- a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeRootSection.kt
+++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/home/HomeRootSection.kt
@@ -149,9 +149,9 @@ class HomeRootSection : Routes.Route() {
}
private val changelogClient by lazy { OkHttpClient() }
- private val changelogStableUrl = "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/changelogs-stable.txt"
- private val changelogPrereleaseUrl = "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/changelogs-prerelease.txt"
- private val announcementsUrl = "https://raw.githubusercontent.com/particle-box/PurrfectSnap/dev/announcements.txt"
+ private val changelogStableUrl = "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/changelogs-stable.txt"
+ private val changelogPrereleaseUrl = "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/changelogs-prerelease.txt"
+ private val announcementsUrl = "https://gitea.majjoduran.app/majjo/XSnap/raw/branch/dev/announcements.txt"
private val heroGradientColors = listOf(
Color(0xFF5C4B99),
@@ -808,7 +808,7 @@ class HomeRootSection : Routes.Route() {
).show()
} else {
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")
UpdateDownloader.downloadAndInstall(context, downloadUrl, "$artifactName.zip", coroutineScope)
}
@@ -984,7 +984,7 @@ class HomeRootSection : Routes.Route() {
},
onGithubClick = {
context.androidContext.openLink(
- "https://github.com/particle-box/PurrfectSnap",
+ "https://gitea.majjoduran.app/majjo/XSnap",
context.translation["toast_open_link_failed"]
)
},
diff --git a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt
index c6666f12..28e92fca 100644
--- a/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt
+++ b/app/src/main/kotlin/me/eternal/purrfectsnap/ui/manager/pages/scripting/ScriptCatalog.kt
@@ -183,7 +183,7 @@ fun ScriptCatalog(root: ScriptingRootSection) {
Button(
onClick = {
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"]
)
},
diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt
index f5d880c0..597e605d 100644
--- a/core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt
+++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/PurrfectSnap.kt
@@ -89,7 +89,7 @@ class PurrfectSnap {
buildString {
append("Snapchat timed out while trying to connect to PurrfectSnap\n\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(" - Excluded PurrfectSnap and Snapchat in HideMyApplist")
},
diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt
index 6aa809f5..bfa350e0 100644
--- a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt
+++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/downloader/MediaDownloader.kt
@@ -215,7 +215,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
private fun downloadOperaMedia(
downloadManagerClient: DownloadManagerClient,
mediaInfoMap: Map
,
- paramMap: ParamMap
+ paramMap: ParamMap,
+ downloadSource: MediaDownloadSource
) {
if (mediaInfoMap.isEmpty()) return
@@ -237,8 +238,19 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
val originalMediaInfo = mediaInfoMap[SplitMediaAssetType.ORIGINAL]!!
val originalMediaInfoReference = handleLocalReferences(originalMediaInfo.uri)
- // Overlay (if present)
+ // Overlay (if present) - skip overlay for all stories
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)
downloadManagerClient.downloadMediaWithOverlay(
@@ -311,7 +323,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
forceAllowDuplicate = forceAllowDuplicate
),
mediaInfoMap,
- paramMap
+ paramMap,
+ MediaDownloadSource.CHAT_MEDIA
)
return
}
@@ -360,7 +373,8 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
forceAllowDuplicate = forceAllowDuplicate
),
mediaInfoMap,
- paramMap
+ paramMap,
+ MediaDownloadSource.STORY
)
return
}
@@ -376,7 +390,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
mediaAuthor = paramMap["CREATOR_DISPLAY_NAME"].toString(),
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate,
- ), mediaInfoMap, paramMap)
+ ), mediaInfoMap, paramMap, MediaDownloadSource.SPOTLIGHT)
return
}
@@ -506,7 +520,7 @@ class MediaDownloader : MessagingRuleFeature("MediaDownloader", MessagingRuleTyp
downloadSource = MediaDownloadSource.PUBLIC_STORY,
creationTimestamp = paramMap["SNAP_TIMESTAMP"]?.toString()?.toLongOrNull(),
forceAllowDuplicate = forceAllowDuplicate,
- ), mediaInfoMap, paramMap)
+ ), mediaInfoMap, paramMap, MediaDownloadSource.PUBLIC_STORY)
}
private fun shouldAutoDownload(keyFilter: String? = null): Boolean {