mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-04-29 22:24:35 +02:00
refactor: reorganize (#15)
* refactor: organization (1/?) open for ideas and suggestions TODO: • Merge UI Hide Elements • Remove Longitude and Latitude from the menu and integrate into the MapActivity • Move New Map UI to Experimental • Shorten „Show Message Content in Notification“ And possibly even more * Merge hide UI Elements bugfix(?): merge overlay * add: download options * add: config listeners * fix(ci): debug remove prod as it's not getting built anymore * fix(messagelogger): clear database bug * update locale, reorganize config * add: set precise location dialog * config: better notifications --------- Co-authored-by: rhunk <101876869+rhunk@users.noreply.github.com>
This commit is contained in:
parent
cfb0ba5d65
commit
85335dafa8
5
.github/workflows/android.yml
vendored
5
.github/workflows/android.yml
vendored
@ -34,8 +34,3 @@ jobs:
|
||||
with:
|
||||
name: app-armv7-release
|
||||
path: app/build/outputs/apk/armv7/debug/*.apk
|
||||
- name: Upload prod
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
with:
|
||||
name: app-prod-release
|
||||
path: app/build/outputs/apk/prod/debug/*.apk
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,10 +1,9 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
local.properties
|
||||
/.idea/
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
.cxx
|
@ -1,22 +1,16 @@
|
||||
{
|
||||
"category": {
|
||||
"general": "General",
|
||||
"spying": "Spying",
|
||||
"media_download": "Media Downloader",
|
||||
"privacy": "Privacy",
|
||||
"ui": "UI",
|
||||
"extras": "Extras",
|
||||
"tweaks": "Tweaks",
|
||||
"location_spoof": "Location Spoof",
|
||||
"experimental": "Experimental",
|
||||
"debugging": "Debugging"
|
||||
"spying_privacy": "Spying & Privacy",
|
||||
"media_manager": "Media Manager",
|
||||
"ui_tweaks": "UI & Tweaks",
|
||||
"experimental_debugging": "Experimental"
|
||||
},
|
||||
|
||||
"action": {
|
||||
"clean_cache": "Clean Cache",
|
||||
"clear_message_logger": "Clear Message Logger",
|
||||
"refresh_mappings": "Refresh Mappings",
|
||||
"open_map": "Pick a location on the map"
|
||||
"open_map": "Choose location on map"
|
||||
},
|
||||
|
||||
"property": {
|
||||
@ -24,16 +18,14 @@
|
||||
"prevent_read_receipts": "Prevent Read Receipts",
|
||||
"hide_bitmoji_presence": "Hide Bitmoji Presence",
|
||||
"show_message_content_in_notifications": "Show Message Content In Notifications",
|
||||
"better_notifications": "Better Notifications",
|
||||
"notification_blacklist": "Notification Blacklist",
|
||||
"message_logger": "Message Logger",
|
||||
"unlimited_snap_view_time": "Unlimited Snap View Time",
|
||||
"auto_download_snaps": "Auto Download Snaps",
|
||||
"auto_download_stories": "Auto Download Stories",
|
||||
"auto_download_public_stories": "Auto Download Public Stories",
|
||||
"auto_download_spotlight": "Auto Download Spotlight",
|
||||
"auto_download_options": "Auto Download Options",
|
||||
"download_options": "Download Options",
|
||||
"download_inchat_snaps": "Download Inchat Snaps",
|
||||
"anti_auto_download_button": "Anti Auto Download Button",
|
||||
"chat_download_context_menu": "Enable Chat Download Context Menu",
|
||||
"auto_download_blacklist": "Auto Download Blacklist",
|
||||
"disable_metrics": "Disable Metrics",
|
||||
"prevent_screenshot_notifications": "Prevent Screenshot Notifications",
|
||||
"prevent_status_notifications": "Prevent Status Notifications (Save to camera roll, missed calls)",
|
||||
@ -42,7 +34,7 @@
|
||||
"menu_slot_id": "Friend Menu Slot ID",
|
||||
"message_preview_length": "Message Preview Length",
|
||||
"gallery_media_send_override": "Gallery Media Send Override",
|
||||
"auto_save": "Auto Save",
|
||||
"auto_save_messages": "Auto Save Messages",
|
||||
"anti_auto_save": "Anti Auto Save Button",
|
||||
"snapchat_plus": "Snapchat Plus",
|
||||
"disable_snap_splitting": "Disable Snap Splitting",
|
||||
@ -62,11 +54,17 @@
|
||||
"meo_passcode_bypass": "My Eyes Only Passcode Bypass",
|
||||
"location_spoof": "Snapmap Location Spoofer",
|
||||
"latitude_value": "Latitude",
|
||||
"longitude_value": "Longitude"
|
||||
"longitude_value": "Longitude",
|
||||
"hide_ui_elements": "Hide UI Elements"
|
||||
},
|
||||
|
||||
"option": {
|
||||
"property": {
|
||||
"better_notifications": {
|
||||
"chat": "Show chat messages",
|
||||
"snap": "Show medias",
|
||||
"reply_button": "Add reply button"
|
||||
},
|
||||
"download_options": {
|
||||
"format_user_folder": "Create folder for each user",
|
||||
"format_hash": "Add a unique hash to the file path",
|
||||
@ -74,10 +72,46 @@
|
||||
"format_date_time": "Add the date and time to the file path",
|
||||
"merge_overlay": "Merge Snap Image Overlays"
|
||||
},
|
||||
"auto_download_options": {
|
||||
"friend_snaps": "Friend Snaps",
|
||||
"friend_stories": "Friend Stories",
|
||||
"public_stories": "Public Stories",
|
||||
"spotlight": "Spotlight"
|
||||
},
|
||||
"auto_save_messages": {
|
||||
"NOTE": "Audio Note",
|
||||
"CHAT": "Chat",
|
||||
"EXTERNAL_MEDIA": "External Media",
|
||||
"SNAP": "Snap",
|
||||
"STICKER": "Sticker"
|
||||
},
|
||||
"notification_blacklist": {
|
||||
"chat": "Chat",
|
||||
"snap": "Snap",
|
||||
"typing": "Typing"
|
||||
},
|
||||
"gallery_media_send_override": {
|
||||
"OFF": "Off",
|
||||
"NOTE": "Audio Note",
|
||||
"SNAP": "Snap",
|
||||
"LIVE_SNAP": "Snap with audio"
|
||||
},
|
||||
"media_quality_level": {
|
||||
"LEVEL_NONE": "Level None",
|
||||
"LEVEL_1": "Level 1",
|
||||
"LEVEL_2": "Level 2",
|
||||
"LEVEL_3": "Level 3",
|
||||
"LEVEL_4": "Level 4",
|
||||
"LEVEL_5": "Level 5",
|
||||
"LEVEL_6": "Level 6",
|
||||
"LEVEL_7": "Level 7",
|
||||
"LEVEL_MAX": "Level Max"
|
||||
},
|
||||
"hide_ui_elements": {
|
||||
"remove_call_buttons": "Remove Call Buttons",
|
||||
"remove_cognac_button": "Remove Cognac Button",
|
||||
"remove_stickers_button": "Remove Stickers Button",
|
||||
"remove_voice_record_button": "Remove Voice Record Button"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -94,6 +128,12 @@
|
||||
"preview": "Preview"
|
||||
},
|
||||
|
||||
"chat_action_menu": {
|
||||
"preview_button": "Preview",
|
||||
"download_button": "Download",
|
||||
"delete_logged_message_button": "Delete Logged Message"
|
||||
},
|
||||
|
||||
"opera_context_menu": {
|
||||
"download": "Download Media"
|
||||
},
|
||||
|
@ -13,7 +13,7 @@ class MessageLoggerRequest(
|
||||
override fun write(bundle: Bundle) {
|
||||
bundle.putString("action", action!!.name)
|
||||
bundle.putString("conversationId", conversationId)
|
||||
bundle.putLong("messageId", messageId!!)
|
||||
bundle.putLong("messageId", messageId ?: 0)
|
||||
bundle.putByteArray("message", message)
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,8 @@ package me.rhunk.snapenhance.config
|
||||
enum class ConfigCategory(
|
||||
val key: String
|
||||
) {
|
||||
GENERAL("category.general"),
|
||||
SPYING("category.spying"),
|
||||
MEDIA_DOWNLOADER("category.media_download"),
|
||||
PRIVACY("category.privacy"),
|
||||
UI("category.ui"),
|
||||
EXTRAS("category.extras"),
|
||||
TWEAKS("category.tweaks"),
|
||||
LOCATION_SPOOF("category.location_spoof"),
|
||||
EXPERIMENTAL("category.experimental");
|
||||
SPYING_PRIVACY("category.spying_privacy"),
|
||||
MEDIA_MANAGEMENT("category.media_manager"),
|
||||
UI_TWEAKS("category.ui_tweaks"),
|
||||
EXPERIMENTAL_DEBUGGING("category.experimental_debugging");
|
||||
}
|
||||
|
@ -12,30 +12,45 @@ enum class ConfigProperty(
|
||||
val nameKey: String,
|
||||
val descriptionKey: String,
|
||||
val category: ConfigCategory,
|
||||
val valueContainer: ConfigValue<*>
|
||||
val valueContainer: ConfigValue<*>,
|
||||
val shouldAppearInSettings: Boolean = true
|
||||
) {
|
||||
|
||||
//SPYING AND PRIVACY
|
||||
MESSAGE_LOGGER("property.message_logger",
|
||||
"description.message_logger",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
PREVENT_READ_RECEIPTS(
|
||||
"property.prevent_read_receipts",
|
||||
"description.prevent_read_receipts",
|
||||
ConfigCategory.SPYING,
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
HIDE_BITMOJI_PRESENCE(
|
||||
"property.hide_bitmoji_presence",
|
||||
"description.hide_bitmoji_presence",
|
||||
ConfigCategory.SPYING,
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
SHOW_MESSAGE_CONTENT_IN_NOTIFICATIONS(
|
||||
"property.show_message_content_in_notifications",
|
||||
"description.show_message_content_in_notifications",
|
||||
ConfigCategory.SPYING,
|
||||
ConfigStateValue(false)
|
||||
BETTER_NOTIFICATIONS(
|
||||
"property.better_notifications",
|
||||
"description.better_notifications",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateListValue(
|
||||
listOf("snap", "chat", "reply_button"),
|
||||
mutableMapOf(
|
||||
"snap" to false,
|
||||
"chat" to false,
|
||||
"reply_button" to false
|
||||
)
|
||||
)
|
||||
),
|
||||
NOTIFICATION_BLACKLIST(
|
||||
"property.notification_blacklist",
|
||||
"description.notification_blacklist",
|
||||
ConfigCategory.SPYING,
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateListValue(
|
||||
listOf("snap", "chat", "typing"),
|
||||
mutableMapOf(
|
||||
@ -45,43 +60,68 @@ enum class ConfigProperty(
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
MESSAGE_LOGGER("property.message_logger", "description.message_logger", ConfigCategory.SPYING, ConfigStateValue(false)),
|
||||
UNLIMITED_SNAP_VIEW_TIME("property.unlimited_snap_view_time", "description.unlimited_snap_view_time", ConfigCategory.SPYING, ConfigStateValue(false)),
|
||||
|
||||
DISABLE_METRICS("property.disable_metrics",
|
||||
"description.disable_metrics",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
BLOCK_ADS("property.block_ads",
|
||||
"description.block_ads",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
UNLIMITED_SNAP_VIEW_TIME("property.unlimited_snap_view_time",
|
||||
"description.unlimited_snap_view_time",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
PREVENT_SCREENSHOT_NOTIFICATIONS(
|
||||
"property.prevent_screenshot_notifications",
|
||||
"description.prevent_screenshot_notifications",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
PREVENT_STATUS_NOTIFICATIONS(
|
||||
"property.prevent_status_notifications",
|
||||
"description.prevent_status_notifications",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
ANONYMOUS_STORY_VIEW(
|
||||
"property.anonymous_story_view",
|
||||
"description.anonymous_story_view",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
HIDE_TYPING_NOTIFICATION(
|
||||
"property.hide_typing_notification",
|
||||
"description.hide_typing_notification",
|
||||
ConfigCategory.SPYING_PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
|
||||
//MEDIA MANAGEMENT
|
||||
SAVE_FOLDER(
|
||||
"property.save_folder", "description.save_folder", ConfigCategory.MEDIA_DOWNLOADER,
|
||||
"property.save_folder", "description.save_folder", ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStringValue(File(
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath + "/Snapchat",
|
||||
"SnapEnhance"
|
||||
).absolutePath)
|
||||
),
|
||||
AUTO_DOWNLOAD_SNAPS(
|
||||
"property.auto_download_snaps",
|
||||
"description.auto_download_snaps",
|
||||
ConfigCategory.MEDIA_DOWNLOADER,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
AUTO_DOWNLOAD_STORIES(
|
||||
"property.auto_download_stories",
|
||||
"description.auto_download_stories",
|
||||
ConfigCategory.MEDIA_DOWNLOADER,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
AUTO_DOWNLOAD_PUBLIC_STORIES(
|
||||
"property.auto_download_public_stories",
|
||||
"description.auto_download_public_stories",
|
||||
ConfigCategory.MEDIA_DOWNLOADER,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
AUTO_DOWNLOAD_SPOTLIGHT(
|
||||
"property.auto_download_spotlight",
|
||||
"description.auto_download_spotlight",
|
||||
ConfigCategory.MEDIA_DOWNLOADER,
|
||||
ConfigStateValue(false)
|
||||
AUTO_DOWNLOAD_OPTIONS(
|
||||
"property.auto_download_options", "description.auto_download_options", ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateListValue(
|
||||
listOf("friend_snaps", "friend_stories", "public_stories", "spotlight"),
|
||||
mutableMapOf(
|
||||
"friend_snaps" to false,
|
||||
"friend_stories" to false,
|
||||
"public_stories" to false,
|
||||
"spotlight" to false
|
||||
)
|
||||
)
|
||||
),
|
||||
DOWNLOAD_OPTIONS(
|
||||
"property.download_options", "description.download_options", ConfigCategory.MEDIA_DOWNLOADER,
|
||||
"property.download_options", "description.download_options", ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateListValue(
|
||||
listOf("format_user_folder", "format_hash", "format_date_time", "format_username", "merge_overlay"),
|
||||
mutableMapOf(
|
||||
@ -93,167 +133,154 @@ enum class ConfigProperty(
|
||||
)
|
||||
)
|
||||
),
|
||||
DOWNLOAD_INCHAT_SNAPS(
|
||||
"property.download_inchat_snaps",
|
||||
"description.download_inchat_snaps",
|
||||
ConfigCategory.MEDIA_DOWNLOADER,
|
||||
CHAT_DOWNLOAD_CONTEXT_MENU(
|
||||
"property.chat_download_context_menu",
|
||||
"description.chat_download_context_menu",
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
ANTI_DOWNLOAD_BUTTON(
|
||||
"property.anti_auto_download_button",
|
||||
"description.anti_auto_download_button",
|
||||
ConfigCategory.MEDIA_DOWNLOADER,
|
||||
DOWNLOAD_BLACKLIST(
|
||||
"property.auto_download_blacklist",
|
||||
"description.auto_download_blacklist",
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
|
||||
DISABLE_METRICS("property.disable_metrics", "description.disable_metrics", ConfigCategory.PRIVACY, ConfigStateValue(false)),
|
||||
PREVENT_SCREENSHOT_NOTIFICATIONS(
|
||||
"property.prevent_screenshot_notifications",
|
||||
"description.prevent_screenshot_notifications",
|
||||
ConfigCategory.PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
PREVENT_STATUS_NOTIFICATIONS(
|
||||
"property.prevent_status_notifications",
|
||||
"description.prevent_status_notifications",
|
||||
ConfigCategory.PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
ANONYMOUS_STORY_VIEW(
|
||||
"property.anonymous_story_view",
|
||||
"description.anonymous_story_view",
|
||||
ConfigCategory.PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
HIDE_TYPING_NOTIFICATION(
|
||||
"property.hide_typing_notification",
|
||||
"description.hide_typing_notification",
|
||||
ConfigCategory.PRIVACY,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
|
||||
MENU_SLOT_ID("property.menu_slot_id", "description.menu_slot_id", ConfigCategory.UI, ConfigIntegerValue(1)),
|
||||
MESSAGE_PREVIEW_LENGTH(
|
||||
"property.message_preview_length",
|
||||
"description.message_preview_length",
|
||||
ConfigCategory.UI,
|
||||
ConfigIntegerValue(20)
|
||||
),
|
||||
|
||||
AUTO_SAVE("property.auto_save", "description.auto_save", ConfigCategory.EXTRAS, ConfigStateValue(false)),
|
||||
ANTI_AUTO_SAVE("property.anti_auto_save", "description.anti_auto_save", ConfigCategory.EXTRAS, ConfigStateValue(false)),
|
||||
SNAPCHAT_PLUS("property.snapchat_plus", "description.snapchat_plus", ConfigCategory.EXTRAS, ConfigStateValue(false)),
|
||||
DISABLE_SNAP_SPLITTING(
|
||||
"property.disable_snap_splitting",
|
||||
"description.disable_snap_splitting",
|
||||
ConfigCategory.EXTRAS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
DISABLE_VIDEO_LENGTH_RESTRICTION(
|
||||
"property.disable_video_length_restriction",
|
||||
"description.disable_video_length_restriction",
|
||||
ConfigCategory.EXTRAS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
OVERRIDE_MEDIA_QUALITY(
|
||||
"property.override_media_quality",
|
||||
"description.override_media_quality",
|
||||
ConfigCategory.EXTRAS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
MEDIA_QUALITY_LEVEL(
|
||||
"property.media_quality_level",
|
||||
"description.media_quality_level",
|
||||
ConfigCategory.EXTRAS,
|
||||
ConfigStateSelection(
|
||||
listOf("LEVEL_NONE", "LEVEL_1", "LEVEL_2", "LEVEL_3", "LEVEL_4", "LEVEL_5", "LEVEL_6", "LEVEL_7", "LEVEL_MAX"),
|
||||
"LEVEL_NONE"
|
||||
)
|
||||
),
|
||||
GALLERY_MEDIA_SEND_OVERRIDE(
|
||||
"property.gallery_media_send_override",
|
||||
"description.gallery_media_send_override",
|
||||
ConfigCategory.EXTRAS,
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateSelection(
|
||||
listOf("OFF", "NOTE", "SNAP", "LIVE_SNAP"),
|
||||
"OFF"
|
||||
)
|
||||
),
|
||||
|
||||
REMOVE_VOICE_RECORD_BUTTON(
|
||||
"property.remove_voice_record_button",
|
||||
"description.remove_voice_record_button",
|
||||
ConfigCategory.TWEAKS,
|
||||
AUTO_SAVE_MESSAGES("property.auto_save_messages",
|
||||
"description.auto_save_messages",
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateListValue(
|
||||
listOf("CHAT", "SNAP", "NOTE", "EXTERNAL_MEDIA", "STICKER")
|
||||
)
|
||||
),
|
||||
ANTI_AUTO_SAVE("property.anti_auto_save",
|
||||
"description.anti_auto_save",
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
REMOVE_STICKERS_BUTTON(
|
||||
"property.remove_stickers_button",
|
||||
"description.remove_stickers_button",
|
||||
ConfigCategory.TWEAKS,
|
||||
|
||||
OVERRIDE_MEDIA_QUALITY(
|
||||
"property.override_media_quality",
|
||||
"description.override_media_quality",
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
REMOVE_COGNAC_BUTTON(
|
||||
"property.remove_cognac_button",
|
||||
"description.remove_cognac_button",
|
||||
ConfigCategory.TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
MEDIA_QUALITY_LEVEL(
|
||||
"property.media_quality_level",
|
||||
"description.media_quality_level",
|
||||
ConfigCategory.MEDIA_MANAGEMENT,
|
||||
ConfigStateSelection(
|
||||
listOf("LEVEL_NONE", "LEVEL_1", "LEVEL_2", "LEVEL_3", "LEVEL_4", "LEVEL_5", "LEVEL_6", "LEVEL_7", "LEVEL_MAX"),
|
||||
"LEVEL_NONE"
|
||||
)
|
||||
),
|
||||
REMOVE_CALL_BUTTONS(
|
||||
"property.remove_call_buttons",
|
||||
"description.remove_call_buttons",
|
||||
ConfigCategory.TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
|
||||
//UI AND TWEAKS
|
||||
HIDE_UI_ELEMENTS(
|
||||
"property.hide_ui_elements",
|
||||
"description.hide_ui_elements",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateListValue(
|
||||
listOf("remove_voice_record_button", "remove_stickers_button", "remove_cognac_button", "remove_call_buttons"),
|
||||
mutableMapOf(
|
||||
"remove_voice_record_button" to false,
|
||||
"remove_stickers_button" to false,
|
||||
"remove_cognac_button" to false,
|
||||
"remove_call_buttons" to false,
|
||||
)
|
||||
)
|
||||
),
|
||||
BLOCK_ADS("property.block_ads", "description.block_ads", ConfigCategory.TWEAKS, ConfigStateValue(false)),
|
||||
STREAK_EXPIRATION_INFO(
|
||||
"property.streak_expiration_info",
|
||||
"description.streakexpirationinfo",
|
||||
ConfigCategory.TWEAKS,
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
DISABLE_SNAP_SPLITTING(
|
||||
"property.disable_snap_splitting",
|
||||
"description.disable_snap_splitting",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
DISABLE_VIDEO_LENGTH_RESTRICTION(
|
||||
"property.disable_video_length_restriction",
|
||||
"description.disable_video_length_restriction",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
SNAPCHAT_PLUS("property.snapchat_plus",
|
||||
"description.snapchat_plus",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
NEW_MAP_UI("property.new_map_ui",
|
||||
"description.new_map_ui",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
NEW_MAP_UI("property.new_map_ui", "description.new_map_ui", ConfigCategory.TWEAKS, ConfigStateValue(false)),
|
||||
|
||||
LOCATION_SPOOF(
|
||||
"property.location_spoof",
|
||||
"description.location_spoof",
|
||||
ConfigCategory.LOCATION_SPOOF,
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
LATITUDE(
|
||||
"property.latitude_value",
|
||||
"description.latitude_value",
|
||||
ConfigCategory.LOCATION_SPOOF,
|
||||
ConfigStringValue("0.0000")
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStringValue("0.0000"),
|
||||
shouldAppearInSettings = false
|
||||
),
|
||||
LONGITUDE(
|
||||
"property.longitude_value",
|
||||
"description.longitude_value",
|
||||
ConfigCategory.LOCATION_SPOOF,
|
||||
ConfigStringValue("0.0000")
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigStringValue("0.0000"),
|
||||
shouldAppearInSettings = false
|
||||
),
|
||||
|
||||
MENU_SLOT_ID("property.menu_slot_id",
|
||||
"description.menu_slot_id",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigIntegerValue(1)
|
||||
),
|
||||
MESSAGE_PREVIEW_LENGTH(
|
||||
"property.message_preview_length",
|
||||
"description.message_preview_length",
|
||||
ConfigCategory.UI_TWEAKS,
|
||||
ConfigIntegerValue(20)
|
||||
),
|
||||
|
||||
// EXPERIMENTAL DEBUGGING
|
||||
USE_DOWNLOAD_MANAGER(
|
||||
"property.use_download_manager",
|
||||
"description.use_download_manager",
|
||||
ConfigCategory.EXPERIMENTAL,
|
||||
ConfigCategory.EXPERIMENTAL_DEBUGGING,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
APP_PASSCODE(
|
||||
"property.app_passcode",
|
||||
"description.app_passcode",
|
||||
ConfigCategory.EXPERIMENTAL,
|
||||
ConfigStringValue("")
|
||||
ConfigCategory.EXPERIMENTAL_DEBUGGING,
|
||||
ConfigStringValue("", isHidden = true)
|
||||
),
|
||||
APP_LOCK_ON_RESUME(
|
||||
"property.app_lock_on_resume",
|
||||
"description.app_lock_on_resume",
|
||||
ConfigCategory.EXPERIMENTAL,
|
||||
ConfigCategory.EXPERIMENTAL_DEBUGGING,
|
||||
ConfigStateValue(false)
|
||||
),
|
||||
MEO_PASSCODE_BYPASS(
|
||||
"property.meo_passcode_bypass",
|
||||
"description.meo_passcode_bypass",
|
||||
ConfigCategory.EXPERIMENTAL,
|
||||
ConfigCategory.EXPERIMENTAL_DEBUGGING,
|
||||
ConfigStateValue(false)
|
||||
);
|
||||
|
||||
|
@ -1,7 +1,22 @@
|
||||
package me.rhunk.snapenhance.config
|
||||
|
||||
abstract class ConfigValue<T> {
|
||||
private val propertyChangeListeners = mutableListOf<(T) -> Unit>()
|
||||
|
||||
fun addPropertyChangeListener(listener: (T) -> Unit) = propertyChangeListeners.add(listener)
|
||||
fun removePropertyChangeListener(listener: (T) -> Unit) = propertyChangeListeners.remove(listener)
|
||||
|
||||
abstract fun value(): T
|
||||
abstract fun write(): String
|
||||
abstract fun read(value: String)
|
||||
abstract fun read(): String
|
||||
protected abstract fun write(value: String)
|
||||
|
||||
protected fun onValueChanged() {
|
||||
propertyChangeListeners.forEach { it(value()) }
|
||||
}
|
||||
|
||||
fun writeFrom(value: String) {
|
||||
val oldValue = read()
|
||||
write(value)
|
||||
if (oldValue != value) onValueChanged()
|
||||
}
|
||||
}
|
@ -3,15 +3,15 @@ package me.rhunk.snapenhance.config.impl
|
||||
import me.rhunk.snapenhance.config.ConfigValue
|
||||
|
||||
class ConfigIntegerValue(
|
||||
var value: Int
|
||||
private var value: Int
|
||||
) : ConfigValue<Int>() {
|
||||
override fun value() = value
|
||||
|
||||
override fun write(): String {
|
||||
override fun read(): String {
|
||||
return value.toString()
|
||||
}
|
||||
|
||||
override fun read(value: String) {
|
||||
override fun write(value: String) {
|
||||
this.value = value.toInt()
|
||||
}
|
||||
}
|
@ -4,17 +4,22 @@ import me.rhunk.snapenhance.config.ConfigValue
|
||||
|
||||
class ConfigStateListValue(
|
||||
private val keys: List<String>,
|
||||
var states: MutableMap<String, Boolean> = mutableMapOf()
|
||||
private var states: MutableMap<String, Boolean> = mutableMapOf()
|
||||
) : ConfigValue<Map<String, Boolean>>() {
|
||||
override fun value() = states
|
||||
|
||||
fun value(key: String) = states[key] ?: false
|
||||
fun setKey(key: String, state: Boolean) {
|
||||
states[key] = state
|
||||
onValueChanged()
|
||||
}
|
||||
|
||||
override fun write(): String {
|
||||
operator fun get(key: String) = states[key] ?: false
|
||||
|
||||
override fun read(): String {
|
||||
return keys.joinToString("|") { "$it:${states[it]}" }
|
||||
}
|
||||
|
||||
override fun read(value: String) {
|
||||
override fun write(value: String) {
|
||||
value.split("|").forEach {
|
||||
val (key, state) = it.split(":")
|
||||
states[key] = state.toBoolean()
|
||||
|
@ -4,25 +4,19 @@ import me.rhunk.snapenhance.config.ConfigValue
|
||||
|
||||
class ConfigStateSelection(
|
||||
private val keys: List<String>,
|
||||
var state: String = ""
|
||||
private var state: String = ""
|
||||
) : ConfigValue<String>() {
|
||||
|
||||
fun keys(): List<String> {
|
||||
return keys
|
||||
}
|
||||
override fun value(): String {
|
||||
|
||||
override fun value() = state
|
||||
|
||||
override fun read(): String {
|
||||
return state
|
||||
}
|
||||
|
||||
fun value(key: String) {
|
||||
state = key
|
||||
}
|
||||
|
||||
override fun write(): String {
|
||||
return state
|
||||
}
|
||||
|
||||
override fun read(value: String) {
|
||||
override fun write(value: String) {
|
||||
state = value
|
||||
}
|
||||
}
|
@ -3,15 +3,15 @@ package me.rhunk.snapenhance.config.impl
|
||||
import me.rhunk.snapenhance.config.ConfigValue
|
||||
|
||||
class ConfigStateValue(
|
||||
var value: Boolean
|
||||
private var value: Boolean
|
||||
) : ConfigValue<Boolean>() {
|
||||
override fun value() = value
|
||||
|
||||
override fun write(): String {
|
||||
override fun read(): String {
|
||||
return value.toString()
|
||||
}
|
||||
|
||||
override fun read(value: String) {
|
||||
override fun write(value: String) {
|
||||
this.value = value.toBoolean()
|
||||
}
|
||||
}
|
@ -3,15 +3,18 @@ package me.rhunk.snapenhance.config.impl
|
||||
import me.rhunk.snapenhance.config.ConfigValue
|
||||
|
||||
class ConfigStringValue(
|
||||
var value: String = ""
|
||||
private var value: String = "",
|
||||
val isHidden: Boolean = false
|
||||
) : ConfigValue<String>() {
|
||||
override fun value() = value
|
||||
|
||||
override fun write(): String {
|
||||
fun hiddenValue() = if (isHidden) value.map { '*' }.joinToString("") else value
|
||||
|
||||
override fun read(): String {
|
||||
return value
|
||||
}
|
||||
|
||||
override fun read(value: String) {
|
||||
override fun write(value: String) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
}
|
||||
|
||||
private fun canMergeOverlay(): Boolean {
|
||||
if (context.config.options(ConfigProperty.DOWNLOAD_OPTIONS)["overlay_merge"] == false) return false
|
||||
if (context.config.options(ConfigProperty.DOWNLOAD_OPTIONS)["merge_overlay"] == false) return false
|
||||
return isFFmpegPresent
|
||||
}
|
||||
|
||||
@ -228,9 +228,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
forceDownload: Boolean
|
||||
) {
|
||||
//messages
|
||||
if (paramMap.containsKey("MESSAGE_ID") &&
|
||||
(forceDownload || context.config.bool(ConfigProperty.AUTO_DOWNLOAD_SNAPS))) {
|
||||
val id = paramMap["MESSAGE_ID"].toString()
|
||||
paramMap["MESSAGE_ID"]?.toString()?.takeIf { forceDownload || canAutoDownload("friend_snaps") }?.let { id ->
|
||||
val messageId = id.substring(id.lastIndexOf(":") + 1).toLong()
|
||||
val senderId: String = context.database.getConversationMessageFromId(messageId)!!.sender_id!!
|
||||
|
||||
@ -244,23 +242,25 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
}
|
||||
|
||||
//private stories
|
||||
val playlistV2Group =
|
||||
if (paramMap.containsKey("PLAYLIST_V2_GROUP")) paramMap["PLAYLIST_V2_GROUP"].toString() else null
|
||||
if (playlistV2Group != null &&
|
||||
playlistV2Group.contains("storyUserId=") &&
|
||||
(forceDownload || context.config.bool(ConfigProperty.AUTO_DOWNLOAD_STORIES))
|
||||
) {
|
||||
val storyIdStartIndex = playlistV2Group.indexOf("storyUserId=") + 12
|
||||
val storyUserId = playlistV2Group.substring(storyIdStartIndex, playlistV2Group.indexOf(",", storyIdStartIndex))
|
||||
paramMap["PLAYLIST_V2_GROUP"]?.toString()?.takeIf {
|
||||
it.contains("storyUserId=") && (forceDownload || canAutoDownload("friend_stories"))
|
||||
}?.let { playlistGroup ->
|
||||
val storyIdStartIndex = playlistGroup.indexOf("storyUserId=") + 12
|
||||
val storyUserId = playlistGroup.substring(
|
||||
storyIdStartIndex,
|
||||
playlistGroup.indexOf(",", storyIdStartIndex)
|
||||
)
|
||||
val author = context.database.getFriendInfo(if (storyUserId == "null") context.database.getMyUserId()!! else storyUserId)
|
||||
|
||||
downloadOperaMedia(mediaInfoMap, author!!.usernameForSorting!!)
|
||||
return
|
||||
}
|
||||
|
||||
val snapSource = paramMap["SNAP_SOURCE"].toString()
|
||||
|
||||
//public stories
|
||||
if ((snapSource == "PUBLIC_USER" || snapSource == "SAVED_STORY") &&
|
||||
(forceDownload || context.config.bool(ConfigProperty.AUTO_DOWNLOAD_PUBLIC_STORIES))) {
|
||||
(forceDownload || canAutoDownload("public_stories"))) {
|
||||
val userDisplayName = (if (paramMap.containsKey("USER_DISPLAY_NAME")) paramMap["USER_DISPLAY_NAME"].toString() else "").replace(
|
||||
"[^\\x00-\\x7F]".toRegex(),
|
||||
"")
|
||||
@ -269,7 +269,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
}
|
||||
|
||||
//spotlight
|
||||
if (snapSource == "SINGLE_SNAP_STORY" && (forceDownload || context.config.bool(ConfigProperty.AUTO_DOWNLOAD_SPOTLIGHT))) {
|
||||
if (snapSource == "SINGLE_SNAP_STORY" && (forceDownload || canAutoDownload("spotlight"))) {
|
||||
downloadOperaMedia(mediaInfoMap, "Spotlight")
|
||||
return
|
||||
}
|
||||
@ -323,11 +323,9 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam
|
||||
}
|
||||
}
|
||||
|
||||
private fun canAutoDownload(): Boolean {
|
||||
return context.config.bool(ConfigProperty.AUTO_DOWNLOAD_SNAPS) ||
|
||||
context.config.bool(ConfigProperty.AUTO_DOWNLOAD_STORIES) ||
|
||||
context.config.bool(ConfigProperty.AUTO_DOWNLOAD_PUBLIC_STORIES) ||
|
||||
context.config.bool(ConfigProperty.AUTO_DOWNLOAD_SPOTLIGHT)
|
||||
private fun canAutoDownload(keyFilter: String? = null): Boolean {
|
||||
val options = context.config.options(ConfigProperty.AUTO_DOWNLOAD_OPTIONS)
|
||||
return options.filter { it.value }.any { keyFilter == null || it.key.contains(keyFilter, true) }
|
||||
}
|
||||
|
||||
override fun asyncOnActivityCreate() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.bridge.common.impl.file.BridgeFileType
|
||||
import me.rhunk.snapenhance.features.BridgeFileFeature
|
@ -1,8 +1,7 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.Logger
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.data.ContentType
|
||||
import me.rhunk.snapenhance.data.MessageState
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.Message
|
||||
import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID
|
||||
@ -61,17 +60,14 @@ class AutoSave : Feature("Auto Save", loadParams = FeatureLoadParams.ACTIVITY_CR
|
||||
|
||||
private fun canSaveMessage(message: Message): Boolean {
|
||||
if (message.messageMetadata.savedBy.any { uuid -> uuid.toString() == myUserId }) return false
|
||||
//only save chats
|
||||
with(message.messageContent.contentType) {
|
||||
if (this != ContentType.CHAT &&
|
||||
this != ContentType.NOTE &&
|
||||
this != ContentType.STICKER &&
|
||||
this != ContentType.EXTERNAL_MEDIA) return false
|
||||
}
|
||||
return true
|
||||
val contentType = message.messageContent.contentType.toString()
|
||||
|
||||
return context.config.options(ConfigProperty.AUTO_SAVE_MESSAGES).filter { it.value }.any { it.key == contentType }
|
||||
}
|
||||
|
||||
private fun canSave(): Boolean {
|
||||
if (context.config.options(ConfigProperty.AUTO_SAVE_MESSAGES).none { it.value }) return false
|
||||
|
||||
with(context.feature(Messaging::class)) {
|
||||
if (lastOpenedConversationUUID == null) return@canSave false
|
||||
val conversation = lastOpenedConversationUUID.toString()
|
||||
@ -87,7 +83,7 @@ class AutoSave : Feature("Auto Save", loadParams = FeatureLoadParams.ACTIVITY_CR
|
||||
context.mappings.getMappedClass("callbacks", "FetchConversationWithMessagesCallback"),
|
||||
"onFetchConversationWithMessagesComplete",
|
||||
HookStage.BEFORE,
|
||||
{ context.config.bool(ConfigProperty.AUTO_SAVE) && canSave()}
|
||||
{ canSave() }
|
||||
) { param ->
|
||||
val conversationId = SnapUUID(param.arg<Any>(0).getObjectField("mConversationId")!!)
|
||||
val messages = param.arg<List<Any>>(1).map { Message(it) }
|
||||
@ -104,7 +100,7 @@ class AutoSave : Feature("Auto Save", loadParams = FeatureLoadParams.ACTIVITY_CR
|
||||
context.mappings.getMappedClass("callbacks", "FetchMessageCallback"),
|
||||
"onFetchMessageComplete",
|
||||
HookStage.BEFORE,
|
||||
{ context.config.bool(ConfigProperty.AUTO_SAVE) && canSave()}
|
||||
{ canSave() }
|
||||
) { param ->
|
||||
val message = Message(param.arg(0))
|
||||
if (!canSaveMessage(message)) return@hook
|
||||
@ -119,7 +115,7 @@ class AutoSave : Feature("Auto Save", loadParams = FeatureLoadParams.ACTIVITY_CR
|
||||
context.mappings.getMappedClass("callbacks", "SendMessageCallback"),
|
||||
"onSuccess",
|
||||
HookStage.BEFORE,
|
||||
{ context.config.bool(ConfigProperty.AUTO_SAVE) && canSave()}
|
||||
{ canSave() }
|
||||
) {
|
||||
val callback = CallbackBuilder(fetchConversationWithMessagesCallbackClass).build()
|
||||
runCatching {
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.features.Feature
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.data.ContentType
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import android.content.Intent
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
@ -17,8 +17,8 @@ class LocationSpoofer: Feature("LocationSpoof", loadParams = FeatureLoadParams.A
|
||||
val longitude = bundle.getFloat("longitude")
|
||||
|
||||
with(context.config) {
|
||||
get(ConfigProperty.LATITUDE).read(latitude.toString())
|
||||
get(ConfigProperty.LONGITUDE).read(longitude.toString())
|
||||
get(ConfigProperty.LATITUDE).writeFrom(latitude.toString())
|
||||
get(ConfigProperty.LONGITUDE).writeFrom(longitude.toString())
|
||||
writeConfig()
|
||||
}
|
||||
context.longToast("Location set to $latitude, $longitude")
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.features.Feature
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationManager
|
||||
@ -206,7 +206,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
|
||||
else it
|
||||
}[MediaType.ORIGINAL] ?: throw Throwable("Failed to download media")
|
||||
|
||||
val bitmapPreview = PreviewUtils.createPreview(downloadedMedia, mediaType == MediaReferenceType.VIDEO)!!
|
||||
val bitmapPreview = PreviewUtils.createPreview(downloadedMedia, mediaType.name.contains("VIDEO"))!!
|
||||
val notificationBuilder = XposedHelpers.newInstance(
|
||||
Notification.Builder::class.java,
|
||||
context.androidContext,
|
||||
@ -227,7 +227,7 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
|
||||
}
|
||||
}
|
||||
|
||||
if (contentType == ContentType.CHAT) {
|
||||
if (contentType == ContentType.CHAT && context.config.options(ConfigProperty.BETTER_NOTIFICATIONS)["reply_button"] == true) {
|
||||
setupNotificationActionButtons(conversationId, notificationData)
|
||||
}
|
||||
|
||||
@ -264,9 +264,8 @@ class Notifications : Feature("Notifications", loadParams = FeatureLoadParams.IN
|
||||
return@hook
|
||||
}
|
||||
|
||||
if (!context.config.bool(ConfigProperty.SHOW_MESSAGE_CONTENT_IN_NOTIFICATIONS)) return@hook
|
||||
|
||||
if (!notificationType.endsWith("CHAT") && !notificationType.endsWith("SNAP")) return@hook
|
||||
if (context.config.options(ConfigProperty.BETTER_NOTIFICATIONS)
|
||||
.filter { it.value }.none { notificationType.endsWith(it.key.uppercase())}) return@hook
|
||||
|
||||
val conversationManager: Any = context.feature(Messaging::class).conversationManager
|
||||
notificationDataQueue[messageId.toLong()] = notificationData
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.features.Feature
|
@ -1,4 +1,4 @@
|
||||
package me.rhunk.snapenhance.features.impl.extras
|
||||
package me.rhunk.snapenhance.features.impl.tweaks
|
||||
|
||||
import me.rhunk.snapenhance.config.ConfigProperty
|
||||
import me.rhunk.snapenhance.data.ContentType
|
@ -22,14 +22,15 @@ class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CRE
|
||||
val chatNoteRecordButton = resources.getIdentifier("chat_note_record_button", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val chatInputBarSticker = resources.getIdentifier("chat_input_bar_sticker", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
val chatInputBarCognac = resources.getIdentifier("chat_input_bar_cognac", "id", Constants.SNAPCHAT_PACKAGE_NAME)
|
||||
|
||||
val hiddenElements = context.config.options(ConfigProperty.HIDE_UI_ELEMENTS)
|
||||
|
||||
Hooker.hook(View::class.java, "setVisibility", HookStage.BEFORE) { methodParam ->
|
||||
val viewId = (methodParam.thisObject() as View).id
|
||||
if (viewId == chatNoteRecordButton && context.config.bool(ConfigProperty.REMOVE_VOICE_RECORD_BUTTON)) {
|
||||
if (viewId == chatNoteRecordButton && hiddenElements["remove_voice_record_button"] == true) {
|
||||
methodParam.setArg(0, View.GONE)
|
||||
}
|
||||
if (viewId == callButton1 || viewId == callButton2) {
|
||||
if (!context.config.bool(ConfigProperty.REMOVE_CALL_BUTTONS)) return@hook
|
||||
if (hiddenElements["remove_call_buttons"] == false) return@hook
|
||||
methodParam.setArg(0, View.GONE)
|
||||
}
|
||||
}
|
||||
@ -45,23 +46,23 @@ class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CRE
|
||||
val view: View = param.arg(0)
|
||||
val viewId = view.id
|
||||
|
||||
if (viewId == chatNoteRecordButton && context.config.bool(ConfigProperty.REMOVE_VOICE_RECORD_BUTTON)) {
|
||||
if (viewId == chatNoteRecordButton && hiddenElements["remove_voice_record_button"] == true) {
|
||||
view.isEnabled = false
|
||||
view.setWillNotDraw(true)
|
||||
}
|
||||
|
||||
if (chatInputBarCognac == viewId && context.config.bool(ConfigProperty.REMOVE_COGNAC_BUTTON)) {
|
||||
if (chatInputBarCognac == viewId && hiddenElements["remove_cognac_button"] == true) {
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
if (chatInputBarSticker == viewId && context.config.bool(ConfigProperty.REMOVE_STICKERS_BUTTON)) {
|
||||
if (chatInputBarSticker == viewId && hiddenElements["remove_stickers_button"] == true) {
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
if (viewId == callButton1 || viewId == callButton2) {
|
||||
if (!context.config.bool(ConfigProperty.REMOVE_CALL_BUTTONS)) return@hook
|
||||
if (hiddenElements["remove_call_buttons"] == false) return@hook
|
||||
if (view.visibility == View.GONE) return@hook
|
||||
}
|
||||
if (viewId == callButtonsStub) {
|
||||
if (!context.config.bool(ConfigProperty.REMOVE_CALL_BUTTONS)) return@hook
|
||||
if (hiddenElements["remove_call_buttons"] == false) return@hook
|
||||
param.setResult(null)
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package me.rhunk.snapenhance.features.impl.ui.menus
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.MotionEvent
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import me.rhunk.snapenhance.R
|
||||
import org.osmdroid.config.Configuration
|
||||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
|
||||
@ -20,12 +23,13 @@ class MapActivity : Activity() {
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
|
||||
@SuppressLint("MissingInflatedId", "ResourceType")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val contextBundle = intent.extras?.getBundle("location") ?: return
|
||||
val latitude = contextBundle.getDouble("latitude")
|
||||
val longitude = contextBundle.getDouble("longitude")
|
||||
val locationLatitude = contextBundle.getDouble("latitude")
|
||||
val locationLongitude = contextBundle.getDouble("longitude")
|
||||
|
||||
Configuration.getInstance().load(applicationContext, getSharedPreferences("osmdroid", Context.MODE_PRIVATE))
|
||||
|
||||
@ -35,7 +39,7 @@ class MapActivity : Activity() {
|
||||
mapView.setMultiTouchControls(true);
|
||||
mapView.setTileSource(TileSourceFactory.MAPNIK)
|
||||
|
||||
val startPoint = GeoPoint(latitude, longitude)
|
||||
val startPoint = GeoPoint(locationLatitude, locationLongitude)
|
||||
mapView.controller.setZoom(10.0)
|
||||
mapView.controller.setCenter(startPoint)
|
||||
|
||||
@ -64,6 +68,28 @@ class MapActivity : Activity() {
|
||||
setResult(RESULT_OK, intent.putExtra("location", bundle))
|
||||
finish()
|
||||
}
|
||||
|
||||
val setPreciseLocationButton = findViewById<Button>(R.id.set_precise_location_button)
|
||||
|
||||
setPreciseLocationButton.setOnClickListener {
|
||||
val locationDialog = layoutInflater.inflate(R.layout.precise_location_dialog, null)
|
||||
val dialogLatitude = locationDialog.findViewById<EditText>(R.id.dialog_latitude).also { it.setText(marker.position.latitude.toString()) }
|
||||
val dialogLongitude = locationDialog.findViewById<EditText>(R.id.dialog_longitude).also { it.setText(marker.position.longitude.toString()) }
|
||||
|
||||
AlertDialog.Builder(this)
|
||||
.setView(locationDialog)
|
||||
.setTitle("Set a precise location")
|
||||
.setPositiveButton("Set") { _, _ ->
|
||||
val latitude = dialogLatitude.text.toString().toDoubleOrNull()
|
||||
val longitude = dialogLongitude.text.toString().toDoubleOrNull()
|
||||
if (latitude != null && longitude != null) {
|
||||
val preciseLocation = GeoPoint(latitude, longitude)
|
||||
mapView.controller.setCenter(preciseLocation)
|
||||
marker.position = preciseLocation
|
||||
mapView.invalidate()
|
||||
}
|
||||
}.setNegativeButton("Cancel") { _, _ -> }.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -64,34 +64,35 @@ class ChatActionMenu : AbstractMenu() {
|
||||
)
|
||||
)
|
||||
}
|
||||
if (context.config.bool(ConfigProperty.DOWNLOAD_INCHAT_SNAPS)) {
|
||||
val previewButton = Button(viewGroup.context)
|
||||
applyButtonTheme(parent, previewButton)
|
||||
previewButton.text = "Preview"
|
||||
previewButton.setOnClickListener {
|
||||
closeActionMenu()
|
||||
context.executeAsync { context.feature(MediaDownloader::class).onMessageActionMenu(true) }
|
||||
}
|
||||
parent.addView(previewButton)
|
||||
}
|
||||
if (context.config.bool(ConfigProperty.CHAT_DOWNLOAD_CONTEXT_MENU)) {
|
||||
parent.addView(Button(viewGroup.context).apply {
|
||||
applyButtonTheme(parent, this)
|
||||
text = this@ChatActionMenu.context.translation.get("chat_action_menu.preview_button")
|
||||
setOnClickListener {
|
||||
closeActionMenu()
|
||||
this@ChatActionMenu.context.executeAsync { this@ChatActionMenu.context.feature(MediaDownloader::class).onMessageActionMenu(true) }
|
||||
}
|
||||
})
|
||||
|
||||
//download snap in chat
|
||||
if (context.config.bool(ConfigProperty.DOWNLOAD_INCHAT_SNAPS)) {
|
||||
val downloadButton = Button(viewGroup.context)
|
||||
applyButtonTheme(parent, downloadButton)
|
||||
downloadButton.text = "Download"
|
||||
downloadButton.setOnClickListener {
|
||||
closeActionMenu()
|
||||
context.executeAsync { context.feature(MediaDownloader::class).onMessageActionMenu(false) }
|
||||
}
|
||||
parent.addView(downloadButton)
|
||||
parent.addView(Button(viewGroup.context).apply {
|
||||
applyButtonTheme(parent, this)
|
||||
text = this@ChatActionMenu.context.translation.get("chat_action_menu.download_button")
|
||||
setOnClickListener {
|
||||
closeActionMenu()
|
||||
this@ChatActionMenu.context.executeAsync {
|
||||
this@ChatActionMenu.context.feature(
|
||||
MediaDownloader::class
|
||||
).onMessageActionMenu(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//delete logged message button
|
||||
if (context.config.bool(ConfigProperty.MESSAGE_LOGGER)) {
|
||||
val downloadButton = Button(viewGroup.context)
|
||||
applyButtonTheme(parent, downloadButton)
|
||||
downloadButton.text = "Deleted logged message"
|
||||
downloadButton.text = context.translation.get("chat_action_menu.delete_logged_message_button")
|
||||
downloadButton.setOnClickListener {
|
||||
closeActionMenu()
|
||||
context.executeAsync {
|
||||
|
@ -21,7 +21,7 @@ import me.rhunk.snapenhance.database.objects.FriendInfo
|
||||
import me.rhunk.snapenhance.database.objects.UserConversationLink
|
||||
import me.rhunk.snapenhance.features.impl.Messaging
|
||||
import me.rhunk.snapenhance.features.impl.downloader.AntiAutoDownload
|
||||
import me.rhunk.snapenhance.features.impl.extras.AntiAutoSave
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.AntiAutoSave
|
||||
import me.rhunk.snapenhance.features.impl.spying.StealthMode
|
||||
import me.rhunk.snapenhance.features.impl.ui.menus.AbstractMenu
|
||||
import me.rhunk.snapenhance.features.impl.ui.menus.ViewAppearanceHelper.applyTheme
|
||||
@ -215,7 +215,7 @@ class FriendFeedInfoMenu : AbstractMenu() {
|
||||
|
||||
run {
|
||||
val userId = context.database.getFriendFeedInfoByConversationId(conversationId)?.friendUserId ?: return@run
|
||||
if (context.config.bool(ConfigProperty.ANTI_DOWNLOAD_BUTTON)) {
|
||||
if (context.config.bool(ConfigProperty.DOWNLOAD_BLACKLIST)) {
|
||||
createToggleFeature(viewModel,
|
||||
viewConsumer,
|
||||
"friend_menu_option.anti_auto_download",
|
||||
|
@ -35,10 +35,11 @@ class SettingsMenu : AbstractMenu() {
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun createPropertyView(viewModel: View, property: ConfigProperty): View {
|
||||
val updateButtonText: (TextView, String) -> Unit = { textView, text ->
|
||||
textView.text = "${context.translation.get(property.nameKey)} $text"
|
||||
textView.text = "${context.translation.get(property.nameKey)}${if (text.isEmpty()) "" else ": $text"}"
|
||||
}
|
||||
val updateStateSelectionText: (TextView, String) -> Unit = { textView, text ->
|
||||
updateButtonText(textView, text.let { if (it.isEmpty()) "(empty)" else ": $it" })
|
||||
|
||||
val updateLocalizedText: (TextView, String) -> Unit = { textView, value ->
|
||||
updateButtonText(textView, value.let { if (it.isEmpty()) "(empty)" else context.translation.get("option." + property.nameKey + "." + it) })
|
||||
}
|
||||
|
||||
val textEditor: ((String) -> Unit) -> Unit = { updateValue ->
|
||||
@ -61,23 +62,29 @@ class SettingsMenu : AbstractMenu() {
|
||||
val resultView: View = when (property.valueContainer) {
|
||||
is ConfigStringValue -> {
|
||||
val textView = TextView(viewModel.context)
|
||||
updateButtonText(textView, property.valueContainer.value)
|
||||
updateButtonText(textView, property.valueContainer.let {
|
||||
if (it.isHidden) it.hiddenValue()
|
||||
else it.value()
|
||||
})
|
||||
ViewAppearanceHelper.applyTheme(viewModel, textView)
|
||||
textView.setOnClickListener {
|
||||
textEditor { value ->
|
||||
property.valueContainer.value = value
|
||||
updateButtonText(textView, value)
|
||||
property.valueContainer.writeFrom(value)
|
||||
updateButtonText(textView, property.valueContainer.let {
|
||||
if (it.isHidden) it.hiddenValue()
|
||||
else it.value()
|
||||
})
|
||||
}
|
||||
}
|
||||
textView
|
||||
}
|
||||
is ConfigIntegerValue -> {
|
||||
val button = Button(viewModel.context)
|
||||
updateButtonText(button, property.valueContainer.value.toString())
|
||||
updateButtonText(button, property.valueContainer.value().toString())
|
||||
button.setOnClickListener {
|
||||
textEditor { value ->
|
||||
runCatching {
|
||||
property.valueContainer.value = value.toInt()
|
||||
property.valueContainer.writeFrom(value)
|
||||
updateButtonText(button, value)
|
||||
}.onFailure {
|
||||
context.shortToast("Invalid value")
|
||||
@ -90,30 +97,30 @@ class SettingsMenu : AbstractMenu() {
|
||||
is ConfigStateValue -> {
|
||||
val switch = Switch(viewModel.context)
|
||||
switch.text = context.translation.get(property.nameKey)
|
||||
switch.isChecked = property.valueContainer.value
|
||||
switch.isChecked = property.valueContainer.value()
|
||||
switch.setOnCheckedChangeListener { _, isChecked ->
|
||||
property.valueContainer.value = isChecked
|
||||
property.valueContainer.writeFrom(isChecked.toString())
|
||||
}
|
||||
ViewAppearanceHelper.applyTheme(viewModel, switch)
|
||||
switch
|
||||
}
|
||||
is ConfigStateSelection -> {
|
||||
val button = Button(viewModel.context)
|
||||
updateStateSelectionText(button, property.valueContainer.value())
|
||||
updateLocalizedText(button, property.valueContainer.value())
|
||||
|
||||
button.setOnClickListener {_ ->
|
||||
val builder = AlertDialog.Builder(viewModel.context)
|
||||
builder.setTitle(context.translation.get(property.nameKey))
|
||||
|
||||
builder.setSingleChoiceItems(
|
||||
property.valueContainer.keys().toTypedArray(),
|
||||
property.valueContainer.keys().toTypedArray().map { context.translation.get("option." + property.nameKey + "." + it) }.toTypedArray(),
|
||||
property.valueContainer.keys().indexOf(property.valueContainer.value())
|
||||
) { _, which ->
|
||||
property.valueContainer.value(property.valueContainer.keys()[which])
|
||||
property.valueContainer.writeFrom(property.valueContainer.keys()[which])
|
||||
}
|
||||
|
||||
builder.setPositiveButton("OK") { _, _ ->
|
||||
updateStateSelectionText(button, property.valueContainer.value())
|
||||
updateLocalizedText(button, property.valueContainer.value())
|
||||
}
|
||||
|
||||
builder.show()
|
||||
@ -123,25 +130,25 @@ class SettingsMenu : AbstractMenu() {
|
||||
}
|
||||
is ConfigStateListValue -> {
|
||||
val button = Button(viewModel.context)
|
||||
updateStateSelectionText(button, property.valueContainer.toString())
|
||||
updateButtonText(button, "(${property.valueContainer.value().count { it.value }})")
|
||||
|
||||
button.setOnClickListener {_ ->
|
||||
val builder = AlertDialog.Builder(viewModel.context)
|
||||
builder.setTitle(context.translation.get(property.nameKey))
|
||||
|
||||
val sortedStates = property.valueContainer.states.toSortedMap()
|
||||
val sortedStates = property.valueContainer.value().toSortedMap()
|
||||
|
||||
builder.setMultiChoiceItems(
|
||||
sortedStates.toSortedMap().map { context.translation.get("option." + property.nameKey + "." +it.key) }.toTypedArray(),
|
||||
sortedStates.map { it.value }.toBooleanArray()
|
||||
) { _, which, isChecked ->
|
||||
sortedStates.keys.toList()[which].let { key ->
|
||||
property.valueContainer.states[key] = isChecked
|
||||
property.valueContainer.setKey(key, isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
builder.setPositiveButton("OK") { _, _ ->
|
||||
updateStateSelectionText(button, property.valueContainer.toString())
|
||||
updateButtonText(button, "(${property.valueContainer.value().count { it.value }})")
|
||||
}
|
||||
|
||||
builder.show()
|
||||
@ -191,15 +198,15 @@ class SettingsMenu : AbstractMenu() {
|
||||
it.key.category
|
||||
}.forEach { (category, value) ->
|
||||
addView(createCategoryTitle(viewModel, category.key))
|
||||
value.forEach {
|
||||
addView(createPropertyView(viewModel, it.key))
|
||||
actions.find { pair -> pair.first.dependsOnProperty == it.key }?.let { pair ->
|
||||
value.filter { it.key.shouldAppearInSettings }.forEach { (property, _) ->
|
||||
addView(createPropertyView(viewModel, property))
|
||||
actions.find { pair -> pair.first.dependsOnProperty == property}?.let { pair ->
|
||||
addView(pair.second())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addView(createCategoryTitle(viewModel, "category.debugging"))
|
||||
//addView(createCategoryTitle(viewModel, "category.debugging"))
|
||||
actions.filter { it.first.dependsOnProperty == null }.forEach {
|
||||
addView(it.second())
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ class ConfigManager(
|
||||
JsonObject::class.java
|
||||
)
|
||||
entries().forEach { (key, value) ->
|
||||
value.read(configObject.get(key.name)?.asString ?: value.write())
|
||||
value.writeFrom(configObject.get(key.name)?.asString ?: value.read())
|
||||
}
|
||||
}
|
||||
|
||||
fun writeConfig() {
|
||||
val configObject = JsonObject()
|
||||
entries().forEach { (key, value) ->
|
||||
configObject.addProperty(key.name, value.write())
|
||||
configObject.addProperty(key.name, value.read())
|
||||
}
|
||||
context.bridgeClient.writeFile(
|
||||
BridgeFileType.CONFIG,
|
||||
|
@ -10,15 +10,15 @@ import me.rhunk.snapenhance.features.impl.downloader.AntiAutoDownload
|
||||
import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader
|
||||
import me.rhunk.snapenhance.features.impl.experiments.AppPasscode
|
||||
import me.rhunk.snapenhance.features.impl.experiments.MeoPasscodeBypass
|
||||
import me.rhunk.snapenhance.features.impl.extras.AntiAutoSave
|
||||
import me.rhunk.snapenhance.features.impl.extras.AutoSave
|
||||
import me.rhunk.snapenhance.features.impl.extras.DisableVideoLengthRestriction
|
||||
import me.rhunk.snapenhance.features.impl.extras.GalleryMediaSendOverride
|
||||
import me.rhunk.snapenhance.features.impl.extras.LocationSpoofer
|
||||
import me.rhunk.snapenhance.features.impl.extras.MediaQualityLevelOverride
|
||||
import me.rhunk.snapenhance.features.impl.extras.Notifications
|
||||
import me.rhunk.snapenhance.features.impl.extras.SnapchatPlus
|
||||
import me.rhunk.snapenhance.features.impl.extras.UnlimitedSnapViewTime
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.AntiAutoSave
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.AutoSave
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.DisableVideoLengthRestriction
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.GalleryMediaSendOverride
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.LocationSpoofer
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.MediaQualityLevelOverride
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.Notifications
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.SnapchatPlus
|
||||
import me.rhunk.snapenhance.features.impl.tweaks.UnlimitedSnapViewTime
|
||||
import me.rhunk.snapenhance.features.impl.privacy.DisableMetrics
|
||||
import me.rhunk.snapenhance.features.impl.privacy.PreventMessageSending
|
||||
import me.rhunk.snapenhance.features.impl.spying.AnonymousStoryViewing
|
||||
|
@ -11,15 +11,34 @@
|
||||
|
||||
</org.osmdroid.views.MapView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/apply_location_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:textSize="20sp"
|
||||
android:background="@android:color/white"
|
||||
android:text="Apply"
|
||||
tools:ignore="HardcodedText,RtlHardcoded" />
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/set_precise_location_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="left"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:padding="10dp"
|
||||
android:background="@android:color/white"
|
||||
android:text="Set Precise Location"
|
||||
android:textSize="20sp"
|
||||
tools:ignore="HardcodedText,RtlHardcoded" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/apply_location_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:background="@android:color/white"
|
||||
android:text="Apply"
|
||||
android:textSize="20sp"
|
||||
tools:ignore="HardcodedText,RtlHardcoded" />
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
28
app/src/main/res/layout/precise_location_dialog.xml
Normal file
28
app/src/main/res/layout/precise_location_dialog.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="20dp"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/dialog_latitude"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="numberDecimal"
|
||||
android:hint="Latitude"
|
||||
android:autofillHints="" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/dialog_longitude"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="numberDecimal"
|
||||
android:hint="Longitude"
|
||||
android:autofillHints="" />
|
||||
|
||||
</LinearLayout>
|
Loading…
x
Reference in New Issue
Block a user