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
1 change: 0 additions & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modifiedapp/libs/snapmod.jar
Binary file not shown.
12 changes: 11 additions & 1 deletion app/src/main/java/xyz/rodit/snapmod/CustomResources.kt
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,10 @@ object CustomResources {
string.menu_option_auto_download to "Auto-Download Snaps",
string.menu_option_export to "Export...",

string.chat_action_playback_speed to "Set Playback Speed"
string.chat_action_playback_speed to "Set Playback Speed",

string.menu_story_enable_auto_download to "Enable Auto-Download Stories",
string.menu_story_disable_auto_download to "Disable Auto-Download Stories"
)

fun init() {
Expand All@@ -37,6 +40,10 @@ object CustomResources {
})
}

fun get(id: Int): String? {
return strings[id]
}

object string {
const val menu_option_stealth_mode = -100000
const val menu_option_preview = -100001
Expand All@@ -45,5 +52,8 @@ object CustomResources {
const val menu_option_export = -100004

const val chat_action_playback_speed = -200000

const val menu_story_enable_auto_download = -300000
const val menu_story_disable_auto_download = -300001
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/xyz/rodit/snapmod/SnapHooks.kt
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,10 +8,12 @@ import android.content.Intent
import android.os.Handler
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.XposedHelpers
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.features.FeatureManager
import xyz.rodit.snapmod.features.InstanceManager
import xyz.rodit.snapmod.logging.XLog
import xyz.rodit.snapmod.logging.dump
import xyz.rodit.snapmod.logging.log
import xyz.rodit.snapmod.mappings.MainActivity
import xyz.rodit.snapmod.util.getList
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,6 +13,7 @@ private const val PINNED_CONVERSATIONS_FILE = "pinned.list"
private const val STEALTH_CONVERSATIONS_FILE = "stealth.list"
private const val AUTO_SAVE_CONVERSATIONS_FILE = "auto_save.list"
private const val AUTO_DOWNLOAD_CONVERSATIONS_FILE = "auto_download.list"
private const val AUTO_DOWNLOAD_STORIES_FILE = "auto_download_stories.list"

class FeatureContext(
val appContext: Context,
Expand All@@ -28,6 +29,7 @@ class FeatureContext(
val stealth: ConversationManager = ConversationManager(appContext.filesDir, STEALTH_CONVERSATIONS_FILE)
val autoSave: ConversationManager = ConversationManager(appContext.filesDir, AUTO_SAVE_CONVERSATIONS_FILE)
val autoDownload: ConversationManager = ConversationManager(appContext.filesDir, AUTO_DOWNLOAD_CONVERSATIONS_FILE)
val autoDownloadStories: ConversationManager = ConversationManager(appContext.filesDir, AUTO_DOWNLOAD_STORIES_FILE)
val arroyo = ArroyoReader(appContext)

var activity: Activity? = null
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,10 +10,7 @@ import xyz.rodit.snapmod.features.messagemenu.MessageMenuModifier
import xyz.rodit.snapmod.features.notifications.FilterTypes
import xyz.rodit.snapmod.features.notifications.ShowMessageContent
import xyz.rodit.snapmod.features.opera.OperaModelModifier
import xyz.rodit.snapmod.features.saving.AutoDownloadSnaps
import xyz.rodit.snapmod.features.saving.ChatSaving
import xyz.rodit.snapmod.features.saving.PublicProfileSaving
import xyz.rodit.snapmod.features.saving.StoriesSaving
import xyz.rodit.snapmod.features.saving.*
import xyz.rodit.snapmod.features.tweaks.*

class FeatureManager(context: FeatureContext) : Contextual(context) {
Expand DownExpand Up@@ -49,6 +46,7 @@ class FeatureManager(context: FeatureContext) : Contextual(context) {

// Saving
add(::AutoDownloadSnaps)
add(::AutoDownloadStories)
add(::ChatSaving)
add(::PublicProfileSaving)
add(::StoriesSaving)
Expand All@@ -67,6 +65,7 @@ class FeatureManager(context: FeatureContext) : Contextual(context) {
add(::HideFriends)
add(::HideStoryReadReceipts)
add(::HideStorySections)
add(::HideStorySectionsLegacy)
add(::LocationOverride)
}

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@ abstract class ButtonOption(context: FeatureContext, name: String, private val t
MenuPlugin(context, name) {

override fun createModel(key: String?): Any {
val actionDataModel = SendChatActionDataModel(createEventData(key!!), false, null)
val actionDataModel = SendChatActionDataModel(createEventData(key!!), false)
val action = SendChatAction(actionDataModel)
val textViewModel = ActionMenuOptionTextViewModel(textResource, null, null, null, null, 62)
return ActionMenuOptionItemViewModel(
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,7 +9,7 @@ abstract class ToggleOption(context: FeatureContext, name: String, private val t
protected abstract fun isToggled(key: String?): Boolean

override fun createModel(key: String?): Any {
val actionDataModel = SendChatActionDataModel(createEventData(key!!), false, null)
val actionDataModel = SendChatActionDataModel(createEventData(key!!), false)
val action = SendChatAction(actionDataModel)
val textViewModel = ActionMenuOptionTextViewModel(textResource, null, null, null, null, 62)
return ActionMenuOptionToggleItemViewModel(
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
package xyz.rodit.snapmod.features.opera

import xyz.rodit.snapmod.CustomResources
import xyz.rodit.snapmod.features.Contextual
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.features.saving.storyId
import xyz.rodit.snapmod.mappings.OperaActionMenuOptionViewModel
import xyz.rodit.snapmod.mappings.OperaContextAction
import xyz.rodit.snapmod.mappings.ParamsMap

class AutoSaveOption(context: FeatureContext) : Contextual(context), MenuPlugin {

override val isEnabled = true

override fun createActions(params: ParamsMap): Collection<OperaActionMenuOptionViewModel> {
return setOf(
OperaActionMenuOptionViewModel(
0,
if (context.autoDownloadStories.isEnabled(params.storyId))
CustomResources.string.menu_story_disable_auto_download
else
CustomResources.string.menu_story_enable_auto_download,
true,
OperaContextAction.HIDE_AD()
)
)
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ package xyz.rodit.snapmod.features.opera
import xyz.rodit.snapmod.features.Contextual
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.mappings.OperaActionMenuOptionViewModel
import xyz.rodit.snapmod.mappings.ParamsMap

private const val KEY_NAME = "action_menu_options"

Expand All@@ -15,23 +16,24 @@ class MenuModifier(context: FeatureContext) : Contextual(context), OperaPlugin {
return true
}

override fun shouldOverride(key: String): Boolean {
override fun shouldOverride(params: ParamsMap, key: String): Boolean {
return KEY_NAME == key
}

override fun override(key: String, value: Any): Any {
override fun override(params: ParamsMap, key: String, value: Any): Any {
if (value !is List<*>) return value
val newList: MutableList<Any> = ArrayList()
newList.addAll(value.filterNotNull())
newList.addAll(
plugins.filter(MenuPlugin::isEnabled)
.flatMap(MenuPlugin::createActions)
.flatMap { it.createActions(params) }
.map(OperaActionMenuOptionViewModel::instance)
)
return newList
}

init {
plugins.add(SaveMenuOption(context))
plugins.add(AutoSaveOption(context))
}
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
package xyz.rodit.snapmod.features.opera

import xyz.rodit.snapmod.mappings.OperaActionMenuOptionViewModel
import xyz.rodit.snapmod.mappings.ParamsMap

interface MenuPlugin {

val isEnabled: Boolean
fun createActions(): Collection<OperaActionMenuOptionViewModel>
fun createActions(params: ParamsMap): Collection<OperaActionMenuOptionViewModel>
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,9 +18,10 @@ class OperaModelModifier(context: FeatureContext) : Feature(context) {
override fun performHooks() {
// Modify opera model map on insert.
ParamsMap.put.before {
val params = ParamsMap.wrap(it.thisObject)
val key = MapKey.wrap(it.args[0]).name
plugins.filter { p -> p.isEnabled && p.shouldOverride(key) }
.forEach { p -> it.args[1] = p.override(key, it.args[1]) }
plugins.filter { p -> p.isEnabled && p.shouldOverride(params, key) }
.forEach { p -> it.args[1] = p.override(params, key, it.args[1]) }
}
}
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
package xyz.rodit.snapmod.features.opera

import xyz.rodit.snapmod.mappings.ParamsMap

interface OperaPlugin {

val isEnabled: Boolean
fun shouldOverride(key: String): Boolean
fun override(key: String, value: Any): Any
fun shouldOverride(params: ParamsMap, key: String): Boolean
fun override(params: ParamsMap, key: String, value: Any): Any
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,13 +4,14 @@ import xyz.rodit.snapmod.features.Contextual
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.mappings.OperaActionMenuOptionViewModel
import xyz.rodit.snapmod.mappings.OperaContextActions
import xyz.rodit.snapmod.mappings.ParamsMap

class SaveMenuOption(context: FeatureContext) : Contextual(context), MenuPlugin {

override val isEnabled: Boolean
get() = context.config.getBoolean("allow_download_stories")

override fun createActions(): Collection<OperaActionMenuOptionViewModel> {
override fun createActions(params: ParamsMap): Collection<OperaActionMenuOptionViewModel> {
return setOf(OperaContextActions.getSaveAction())
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ package xyz.rodit.snapmod.features.opera

import xyz.rodit.snapmod.features.Contextual
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.mappings.ParamsMap
import xyz.rodit.snapmod.mappings.StoryAutoAdvanceMode
import xyz.rodit.snapmod.mappings.StoryMediaPlaybackMode

Expand All@@ -13,11 +14,11 @@ class SnapDurationModifier(context: FeatureContext) : Contextual(context), Opera
override val isEnabled: Boolean
get() = context.config.getBoolean("unlimited_snap_duration")

override fun shouldOverride(key: String): Boolean {
override fun shouldOverride(params: ParamsMap, key: String): Boolean {
return KEY_AUTO_ADVANCE_MODE == key || KEY_MEDIA_PLAYBACK_MODE == key
}

override fun override(key: String, value: Any): Any {
override fun override(params: ParamsMap, key: String, value: Any): Any {
if (KEY_AUTO_ADVANCE_MODE == key) {
return StoryAutoAdvanceMode.NO_AUTO_ADVANCE().instance
} else if (KEY_MEDIA_PLAYBACK_MODE == key) {
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,7 +19,7 @@ class AutoDownloadSnaps(context: FeatureContext) : Feature(context, 84608.toMax(

val params = ParamsMap.wrap(viewController.metadata.instance)
val map = params.map
if (!map.containsKey(MessageStoryKeys.getSnapInSavedState().instance)) return@after
if (!params.isChat) return@after

val messageId = map[MessageStoryKeys.getMessageId().instance] as String?
val conversationId = UUID.wrap(map[ConversationStoryKeys.getConversationId().instance])
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
package xyz.rodit.snapmod.features.saving

import xyz.rodit.snapmod.features.Feature
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.mappings.OperaDisplayState
import xyz.rodit.snapmod.mappings.OperaPageViewController
import xyz.rodit.snapmod.mappings.ParamsMap
import xyz.rodit.snapmod.util.PathManager
import xyz.rodit.snapmod.util.after
import xyz.rodit.snapmod.util.toMax

class AutoDownloadStories(context: FeatureContext) : Feature(context, 84608.toMax()) {

override fun performHooks() {
OperaPageViewController.onDisplayStateChanged.after {
val viewController = OperaPageViewController.wrap(it.thisObject)
if (viewController.state.instance != OperaDisplayState.FULLY_DISPLAYED().instance) return@after

val params = ParamsMap.wrap(viewController.metadata.instance)
if (params.isChat) return@after

val storyId = params.storyId
if (!context.config.getBoolean("auto_download_stories")
&& !context.autoDownloadStories.isEnabled(storyId)
) return@after

getMediaInfo(context, params) { info ->
downloadOperaMedia(
context,
PathManager.DOWNLOAD_STORY,
info
)
}
}
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,7 +53,7 @@ class ChatSaving(context: FeatureContext) : Feature(context) {
}

// Map live snap model hashCode to media object for download later.
ChatModelLiveSnap.constructors.after(context, "allow_save_snaps") {
ChatModelWithMedia.constructors.after(context, "allow_save_snaps") {
val hashCode = it.thisObject.hashCode()
chatMediaMap[hashCode] = it.args[6]
}
Expand All@@ -66,7 +66,7 @@ class ChatSaving(context: FeatureContext) : Feature(context) {
lastMessageData = base.messageData

when {
ChatModelLiveSnap.isInstance(it.args[2]) -> {
ChatModelWithMedia.isInstance(it.args[2]) -> {
// Convert live snap to saved snap.
val hashCode = it.args[2].hashCode()
val media = LiveSnapMedia.wrap(chatMediaMap[hashCode])
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,48 @@
package xyz.rodit.snapmod.features.saving

import xyz.rodit.snapmod.CustomResources
import xyz.rodit.snapmod.createDelegate
import xyz.rodit.snapmod.features.Feature
import xyz.rodit.snapmod.features.FeatureContext
import xyz.rodit.snapmod.mappings.ContextActionMenuModel
import xyz.rodit.snapmod.mappings.Func1
import xyz.rodit.snapmod.mappings.OperaContextAction
import xyz.rodit.snapmod.mappings.ParamsMap
import xyz.rodit.snapmod.util.PathManager
import xyz.rodit.snapmod.util.after

class StoriesSaving(context: FeatureContext) : Feature(context) {

override fun performHooks() {
// Override save story click.
// Override custom options click.
ContextActionMenuModel.constructors.after(context, "allow_download_stories") {
val model = ContextActionMenuModel.wrap(it.thisObject)
if (model.action.instance !== OperaContextAction.SAVE().instance) return@after

val clickProxy = Func1.getMappedClass().createDelegate(context.classLoader) { _, args ->
val map = ParamsMap.wrap(args[0])
getMediaInfo(context, map) {
downloadOperaMedia(context, PathManager.DOWNLOAD_STORY, it)
}
null
if (model.action.instance == OperaContextAction.SAVE().instance) {
val clickProxy =
Func1.getMappedClass().createDelegate(context.classLoader) { _, args ->
val params = ParamsMap.wrap(args[0])
getMediaInfo(context, params) { info ->
downloadOperaMedia(context, null, info)
}
null
}
model.onClick = Func1.wrap(clickProxy)
} else if (model.text == CustomResources.get(CustomResources.string.menu_story_disable_auto_download)) {
model.onClick = createAutoDownloadClickProxy(false)
} else if (model.text == CustomResources.get(CustomResources.string.menu_story_enable_auto_download)) {
model.onClick = createAutoDownloadClickProxy(true)
}
model.onClick = Func1.wrap(clickProxy)
}
}

private fun createAutoDownloadClickProxy(enable: Boolean) =
Func1.wrap(
Func1.getMappedClass().createDelegate(context.classLoader) { _, args ->
val params = ParamsMap.wrap(args[0])
val storyId = params.storyId
if (enable) context.autoDownloadStories.enable(storyId)
else context.autoDownloadStories.disable(storyId)
null
}
)
}
Loading